In the previous article, we looked briefly at the first step in getting started with RxSwift, implementing a logon input listening verification function with the help of RxCocoa. So how do we create our own listening sequence? Or how do we listen for properties that we’ve created ourselves, like a String.

Observables and Observers are different and related

Observable: **Observable: **Observable: **Observable: **Observable: **Observable

An Observer is a person who listens to a sequence. Listen for the event, which it then needs to respond to. For example, an onNext event is listened on, and we respond to that event.

The two cooperate with each other to achieve the effect of response.

Observable listens for sequences

Observable as the foundation of Rx, we should first have some basic understanding of it. ###1. Observable

  • Observable<T>This class isRxThe basis of the framework is what we might call an observable sequence. What it does is it can asynchronously produce a series ofEvent(event), i.eObservable<T>Objects are issued irregularly over timeevent(element : T)Such a thing.
  • And theseEventIt can also carry data, it’s generic<T>That’s what it’s used to specifyEventThe type of data carried.
  • So with the observable sequence, we need another oneObserverTo subscribe to it so that the subscriber can receive itObservable<T>From time to timeEvent.

2.Event

If you look at the RxSwift source code, you can find that the Event is defined as follows:

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
}

Copy the code

You can see that an Event is an enumeration, which means that an Observable emits three different types of events:

  • Next: The next event is the one that can carry data

    , which is arguably the “most normal” event.

  • Error: An error event represents an error. It can carry specific error content. Once an Observable emits an error event, the Observable terminates and never emits any more events.

  • Completed: A completed event indicates that the event emitted by an Observable terminates normally. Like error, once a Completed event is emitted, the Observable terminates. It will never emit an event again.

The Observer observers

As mentioned above, an Observer is used to “observe” an Observable. How do they do this? We use the subscribe() method to subscribe to an Observable. Observables emit three events: Next, error, and completed. The Observer can also listen to these three events

        // Subscribe to the sequence
        observable.subscribe(onNext: { (str) in
            print(str)
        }, onError: { (error) in
            print(error)
        }, onCompleted: {
            print("completed")
        }).disposed(by: disposebag)
Copy the code

Observable and Observer

1. Most common sequence creation and subscription
        enum MyError: Error {
            case errorA
            case errorB
        }
        // Create sequence
        let testOB = Observable<String>.create { ob in
            // Send the next event
            ob.onNext("test1")
            ob.onNext("test2")
            ob.onNext("test3")
            // Send an error event
            ob.onError(MyError.errorA)
            // Send the completed event
            ob.onCompleted()
            return Disposables.create()
        }
        
        // Subscribe to the sequence
        testOB.subscribe(onNext: { (str) in
            print(str)
        }, onError: { (error) in
            print(error)
        }, onCompleted: {
            print("completed")
        }).disposed(by: disposebag)
Copy the code

Print result:

test1
test2
test3
errorA
Copy the code

Careful friends have noticed that we sent completed but did not print it out. Obviously, the problem is ob.onerror (). Let’s test this by moving ob.onError()

        // Create sequence
        let testOB = Observable<String>.create { ob in
            ob.onNext("test1")
            ob.onNext("test2")
            ob.onError(MyError.errorA)
            ob.onNext("test3")
            ob.onCompleted()
            return Disposables.create()
        }
Copy the code

Print result:

test1
test2
errorA
Copy the code

So we can conclude that once the observer is listening for an error event, it will stop listening after the onError: closure is raised. I think we’ll talk about that later. Let’s try to understand it for a moment.

2. Use across classes

We create a new class, FirstViewModel, which declares an Observable

variable and creates it directly in the initialization method.

class FirstViewModel {
    var text : Observable<String>!
    
    let disposeBag = DisposeBag(a)init() {
        text  = Observable.create { (observer) -> Disposable in
            observer.onNext("test1")
            observer.onNext("test2")
            observer.onNext("test3")
            observer.onCompleted()
            return Disposables.create()
        }
    }
}
Copy the code

And then we initialize FirstViewModel in our controller

class FirstViewController: UIViewController {

    var disposeBag = DisposeBag(a)override func viewDidLoad(a) {
        super.viewDidLoad()
        
        let vm : FirstViewModel = FirstViewModel.init()
        vm.text.subscribe(onNext: { obString in
            print(obString)
        }, onCompleted: {
            print("completed")
        }).disposed(by: disposeBag)
    }
}
Copy the code

Command + R to view the output

msg1
msg2
msg3
completed
Copy the code
3. Click the button to send the event
class FirstViewModel {
   class func getText() - >Observable<String> {
        // Create a just event
        return  .just("Did you get it?")}}Copy the code
btn.rx.tap.subscribe(onNext: { [weak self] in
    self? .btnClick() }).disposed(by: disposeBag)/ / event
func btnClick(a) -> Void{
    FirstViewModel.getText().subscribe(onNext: { (String) in
        print(String)// Output result: you got it
    }).disposed(by: disposeBag)
}
Copy the code

There’s a — just, what is this. There are several ways to create an Observable sequence.

Other methods to create the Observable sequence

The difference between each method and its effect is shown here

        print("----------- this is just ----------- ")
        
        let observable_just = Observable<Int>.just(5)
        observable_just.subscribe(onNext: { (Int) in
            print("\(Int)")
        }, onCompleted: {
            print("just completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is of ----------- ")
        let observable_of = Observable.of("A"."B"."C")
        observable_of.subscribe(onNext: { (String) in
            print("\(String)")
        }, onCompleted: {
            print("of completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is from ----------- ")
        let observable_from = Observable.from(["A"."B"."C"])
        observable_from.subscribe(onNext: { (String) in
            print("\(String)")
        }, onCompleted: {
            print("from completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is empty ----------- ")
        let observable_empty = Observable<Int>.empty()
        observable_empty.subscribe(onNext: { (Int) in
            print("this is empty")
        }, onCompleted: {
            print("empty completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is never ----------- ")
        let observable_nerver = Observable<Int>.never()
        observable_nerver.subscribe(onNext: { (Int) in
            print("this is never")
        }, onCompleted: {
            print("never completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is error ----------- ")
        enum MyError: Error {
            case A
            case B
        }
        
        let observable_error = Observable<Int>.error(MyError.A)
        observable_error.subscribe(onNext: { (Int) in
            
        }, onError: { (Error) in
            print(" \(Error)")
        }, onCompleted: {
            print("error completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is range ----------- ")
        let observable_range = Observable.range(start: 1.count: 5)
        observable_range.subscribe(onNext: { (Int) in
            print("\(Int)")
        }, onCompleted: {
            print("range completed")
        }).disposed(by: disposeBag)
        
        // Can not be placed in the main thread, it will block
// let observable_repeat = Observable.repeatElement(1)
// observable_repeat.subscribe(onNext: { (Int) in
// print("this is repeat -- \(Int)")
// }, onCompleted: {
// print("repeat completed")
// }).disposed(by: disposeBag)
        
        print("----------- this is generate ----------- ")
        // Use generate()
        let observable_generate = Observable.generate(
            initialState: 0,
            condition: { $0< =10 },
            iterate: { $0 + 2 }
        )
        observable_generate.subscribe(onNext: { (Int) in
             print("\(Int)")
        }, onCompleted: {
            print("generate completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is deferred ----------- ")
        // Is used to indicate whether it is odd or even
        var isOdd = true
        
        // Defer Observable initialization with the Deferred () method, pass the block to initialize the Observable and return it.
        let factory : Observable<Int> = Observable.deferred {
            
            // alternate odd and even numbers every time this block is executedisOdd = ! isOdd// Based on the isOdd parameter, determine whether an odd or even Observable is created and returned
            if isOdd {
                return Observable.of(1.3.5 ,7)}else {
                return Observable.of(2.4.6.8)}}// First subscription test
        factory.subscribe { event in
            print("\(isOdd)", event)
        }.disposed(by: disposeBag)
        
        // Second subscription test
        factory.subscribe { event in
            print("\(isOdd)", event)
        }.disposed(by: disposeBag)
        // The third subscription test
        factory.subscribe { event in
            print("\(isOdd)", event)
        }.disposed(by: disposeBag)
        
        //RxSwift 5.x deprecates TimeInterval and DispatchTimeInterval instead
        print("----------- this is interval ----------- ")
         let observable_interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
        
        observable_interval.subscribe { event in
            print(event)
        }.disposed(by: disposeBag)
        
        print("----------- this is timer ----------- ")
        // Emits a unique element 0 after 5 seconds
        let observable_timer = Observable<Int>.timer(.seconds(5), scheduler: MainScheduler.instance)
        observable_timer.subscribe { event in
            print(event)
        }.disposed(by: disposeBag)

        // Emit an element every 1 second after a delay of 5 seconds
        let observable_timer2 = Observable<Int>.timer(.seconds(5), period: .seconds(5), scheduler: MainScheduler.instance)
        observable_timer2.subscribe { event in
            print(event)
        }.disposed(by: disposeBag)
        
Copy the code

Observable and Observer

Well, like TextField, we can either listen to it, or we can use it as an observer.

  • If you’re a beginner, this is a strange sentence. What does this mean as an observer? We can think of it this way: we can either listen for input to a text box, or we can assign values to a text box.

So I’m going to introduce you to this situation.

class FifthViewController: UIViewController {
    var textF:UITextField!
    
    let disposeBag = DisposeBag(a)override func viewDidLoad(a) {
        super.viewDidLoad()

        textF = UITextField.init(frame: .init(x: 20, y: 120, width: view.frame.width, height: 40))
        textF.borderStyle = .roundedRect
        view.addSubview(textF)
      
        // Use the text box as an observer
        let observer = textF.rx.text
        
        let text:Observable<String> = Observable<String>.create {
            $0.onNext("test")
            $0.onNext("test1")
            $0.onNext("test2")
            return Disposables.create()
        }
        text.bind(to: observer).disposed(by: disposeBag)
        
        // treat the textbox as a listener
        let observable = textF.rx.text
        observable.subscribe(onNext: {
            print($0 as Any)
        }).disposed(by: disposeBag)
        
    }
}
Copy the code

In addition, the framework defines helper types that are both listener sequences and observers. If you can use these helper types properly, they can help you describe the characteristics of things more accurately:

  • AsyncSubject
  • PublishSubject
  • ReplaySubject
  • BehaviorSubject
  • ControlProperty”

Excerpt from: RxSwift Chinese documentation.

I will explore the above types of assistance in RxSwfit Study Notes (4)