Let's create a helper function called executeProcedure(with description:String, procedure: () -> Void). The function takes two params: a string description and a procedure closure. It will print the description and will execute the procedure. We will use this function to encapsulate each procedure and make it easier to determine what each procedure is printing to the console:
import UIKit
import RxSwift
public func executeProcedure(for description:String, procedure: () -> Void){
print("Procedure executed for:", description)
procedure()
}
Firstly, we will cut and paste this function to a separate file in the Sources folder for this playground. By twisting down the playground page in the project navigator, right-click on the Sources folder and select a new file; name it Helper. Now select the playground file again, cut the executeProcedure(with description:String, procedure: () -> Void) function, and paste it into the support code file. The project structure in the project navigator will look something like this:

Build the project once again to make the function available to the main playground file.
Previously, we explained that events are emitted by an Observable sequence. So now, we will create a few examples of observable sequences, and we will observe them emitting some events.
Let's start by creating the simplest of Observables, a single element sequence using the just operator:
executeProcedure(for: "just"){
let observable = Observable.just("Example of Just Operator!")
}

By clicking the option on the just operator, you can see that it returns an Observable sequence of a single element of a String type.
Now we will look at the subscribe operator to subscribe to events being emitted by an Observable and print each event as it is emitted:
executeProcedure(for: "just"){
let observable = Observable.just("Example of Just Operator!")
observable.subscribe({ (event: Event<String>) in
print(event)
})
}
subscribe takes a closure that receives the emitted event and will execute this closure each time an event is emitted. We manually define the event argument that is passed to subscribe's closure as being an event of the String type, and then we print each event as it is emitted. The result is the single next event that we created with the String Example of Just Operator! followed by the completed event:

Remember that we have three types of Observable events:
- next
- error
- completed
Also, once an error or a completed event is emitted, the Observable sequence is terminated and cannot emit additional events. The event param is an enumeration of the type event of Element:
/// Represents a sequence event.
///
/// Sequence grammar:
/// **next\* (error | completed)**
public enum Event<Element> {
/// Next element is produced.
case next(Element)
/// Sequence terminated with an error.
case error(Swift.Error)
/// Sequence completed successfully.
case completed
}
Element is a generic placeholder for the Observable's type, a String in this example. We explicitly specified String, but if we hadn't, it could also be inferred by the type the observable instance's subscribe is called on.
Next, we will create an Observable sequence with multiple elements using the of operator:
executeProcedure(for: "of"){
let observable = Observable.of(10, 20, 30)
observable.subscribe({
print($0)
})
}
We created an Observable with elements 10, 20, 30 and subscribed to this sequence to print out the sequence, just like the previous example, except that this time we used the $0 shorthand argument name instead of explicitly declaring an argument name. Each next event is printed followed by the completed event:

Let's create an observable sequence from an array using the from operator:
executeProcedure(for: "from"){
Observable.from([10, 20,30])
.subscribe{
print($0)
}
}
As you can see, we have not declared a variable to assign the returned value as we did in the previous examples. We then chained the subscription onto the Observable sequence returned and wrapped the subscription onto the next line to improve readability. The output of the preceding method will be as follows:

This is how you will typically see chained operators. Let's command + click and see the subscribe operator's source:

As you can see, subscribe returns Subscription object used to unsubscribe from the observable sequence. This subscription object is of the type that confirms to the Disposable protocol that represents any disposable resource. After we command + click on the Disposable protocol, we find that it requires a dispose() method to be implemented:

Digging into the source like this can really help you understand how RxSwift works. Let's go back to the playground and assign the result we returned from subscribe to a local variable subscribed, which is of the Disposable type:

Disposing of a subscription will cause the underlying Observable sequence to emit a completed event and terminate. In these basic examples, we have explicitly defined all the Observable sequence elements ahead of time, and they will automatically emit a completed event after emitting the last next event. More often than not though, an Observable sequence can continue to emit events, and they must be manually terminated or else you will leak that memory. So the right thing to do here is to ensure that subscription is disposed of when we are done with it. One way to do that is by calling dispose():
executeProcedure(for: "from"){
let subscribed = Observable.from([10, 20,30])
.subscribe{
print($0)
}
subscribed.dispose()
}
That's actually not done in practice though; the more conventional approach is to add subscriptions to a container that holds disposables and will call dispose() on its contents on its deInit. That container is called a DisposeBag. We will create a DisposeBag instance before the subscription:
executeProcedure(for: "from"){
let disposeBag = DisposeBag()
let subscribed = Observable.from([10, 20,30])
.subscribe(onNext:{
print($0)
})
subscribed.disposed(by: disposeBag)
}
Then, we add the subscription to disposeBag using the disposed(by:) method.
If you just want to get the next event elements, instead of getting each next event containing an element, you can use the subscribe(onNext:) operator instead, as done in the preceding code. The output of the code will be this:

As you can see, only the next event elements are printed and the completed event is ignored. The following points are worthy to be noted:
- If an error event was emitted, it will be ignored too, because we have subscribed to next events only
- We can actually subscribe to get next, completed and/or error events and react when the subscription is terminated and disposed of for any reason
For example, let's create a sequence from another array of Int values:
Observable.from([1, 2, 3])
This time, we will choose subscribe on all the possible events, as follows:
.subscribe(onNext: nil, onError: nil, onCompleted: nil, onDisposed: nil)
// nil is written in this case just to shorten the format
Note that each of these parameters is an option, so you can skip one or more of them if you want to. For example, let's remove onError from the function:
.subscribe(onNext: nil, onCompleted: nil, onDisposed: nil)
We are now just subscribing to onNext, onCompletion and onDisposed events. Let's print the elements from the next events, and print completion message onCompleted event and the Disposed message as soon as the sequence terminates:
Observable.from([1, 2, 3])
.subscribe(onNext: {print($0)},
onCompleted:
{print("Completed the events")},
onDisposed: {print("Sequence terminated hence Disposed")}
)
Finally, we will add the subscription to DisposeBag:
Observable.from([1, 2, 3])
.subscribe(onNext: {print($0)},
onCompleted: {print("Completed the events")},
onDisposed: {print("Sequence terminated hence Disposed")}
)
.disposed(by: disposeBag)
Sometimes we have to manually indent RxSwift code, and we can do so by selecting the code block and pressing control + I. Try this activity and note the difference. Meanwhile, check the output:

As expected, all the next events are printed, followed by the completed event and finally disposed is called.
As we are working with finite Observable sequences here, they automatically emit completed events and terminate after the last element. It's better to be safe than sorry, so just get into the habit of always adding subscriptions to a disposeBag, and you will avoid potentially leaking memory. Let's look at an example of subscribing to an error event at this point:
executeProcedure(for: "error"){
enum CustomError: Error{
case defaultError
}
let disposeBag = DisposeBag()
Observable<Void>.error(CustomError.defaultError)
.subscribe(onError: {print($0)})
.disposed(by: disposeBag)
}
First, we created a CustomError enum with a single case of defaultError and then we have created an Observable sequence that terminates with an error using the error operator that takes an error as a parameter. It's necessary to specify the type to the observable sequence here, so we just used Void; then we subscribed on the error operator to print the error. Lastly, we disposed of the subscription by adding it to a dispose bag. You can see the output:

This was just a small example; we will work with errors in more detail in the upcoming chapters. In the next sections, we will go over some special kinds of Observable called subjects that can continue to emit new events to subscribers. In Chapter 2, FRP Fundamentals, Terminology, and Basic Building Blocks, we described a subject and various types of subject in theory, and now we will work with all those concepts in code, starting with PublishSubject.