Driver

Case introduced

Request a network and bind to the UI

Using Observerable

let result0 = inputTF.rx.text.skip(1) .flatMap { [weak self](input) -> Observable<Any> in return (self? .dealwithData(inputText:input ?? ""))! .observeon (mainscheduler.instance).catchErrorJustreturn (" error event detected ")}.share(replay: 1, scope: .whileConnected) // share(replay: 1, scope: Result0. Subscribe (onNext: whileConnected) Result0: \(element) in print(" Result0: \(element)")}). Subscribe (by: disposeBag) result0. Subscribe (onNext: {(element) in print(" Result0: \(element) - \(thread.current)")}). Disposed (by: disposeBag)Copy the code

The Driver

Titlt - non-error let result = inputtf.rx.text.orempty.asdriver ().flatmap {return Self. dealwithData(inputText: $0).asDriver(onErrorJustReturn: "Error event detected ")} result.map {" Length: \(($0 as! String).count)"} .drive(self.textLabel.rx.text) .disposed(by: disposeBag) result.map { "\($0 as! String)"} .drive(self.btn.rx.title()) .disposed(by: disposeBag)Copy the code
Observable<Any>{print(" request network \(thread.current)") // data return Observable<Any>.create({ (ob) -> Disposable in if inputText == "1234" { ob.onError(NSError.init(domain: "Com.pxwx.www ", code: 10086, userInfo: nil))} dispatchqueue.global ().async {print(" Send before look: \(thread.current)") ob.onnext (" Already entered :\(inputText)") ob.oncompleted ()} return Disposables. Create ()})}Copy the code

What is an old driver

Drivers are arguably the most complex traits, and their goal is to provide an easy way to write responsive code at the UI layer. 2. We can use it if our sequence column meets the following characteristics:

  • No error events are generated
  • Must be listening on the MainScheduler
  • Shared state changes (shareReplayLatestWhileConnected)

Why use Driver?

The most common use of a Driver is when a sequence is required to drive an application, such as:

  • The UI is driven through the CoreData model
  • Use one UI element value (binding) to drive another UI element value

2. As with normal operating system drivers, the application will stop responding to user input if a sequential column error occurs. 3. It is also extremely important to observe these elements on the main thread, because UI elements and application logic are generally not thread-safe. 4. In addition, use the observable sequence column that builds the Driver, which shares state changes.

Basic Source code parsing

A Driver is simply an alias for a sequence that is easy to remember.

public typealias Driver<Element> = SharedSequence<DriverSharingStrategy, Element>
Copy the code

OK! We see source.share(replay: 1, scope:.whileconnected) as a Driver that encapsulates a sequence.

Subject

Let’s look at a very special type — Subject. Why is it special? The reason is simple: Subject can act as both sequence and observer, so it is widely used in practical development because of this characteristic. Let’s interpret this particular Subject.

The basic principle of

First, let’s look at how SubjectType works

Public Protocol SubjectType: ObservableType {// AssociatedType SubjectObserverType subjecTOBType: ObserverType func asObserver() -> SubjectObserverType }Copy the code
  • SubjectTypeThe first is inheritanceObservableType, with sequence characteristics
  • Associated with the observer type, has the ability of that type
  • Let’s get a feel for ‘subject’ through a concrete type

  • Obviously being able to subscribe to signals (the basic ability of sequences)
  • The ability to send a response, again, is the observer’s ability
  • View the underlying source code analysis

Subscription response process

  • self._observers.insert(observer.on):By adding all subscription events to a collection, it is obvious that they are all executed at once in the right place
  • It also returns the destroyer of this subscription to facilitate cleanup:synchronizedUnsubscribe->self._observers.removeKey(disposeKey)

  • Convenience bykeyGet a responsebagTo perform collection removal
  • Because there is no corresponding holding relationship, automatic release destruction is achieved

Signal sending process

  • This place might look a little messy and gross to you, but you can see it from the heart
  • This is basically calleddispatchThe function passes two arguments:self._synchronized_on(event)andevent
  • To viewdispatchFunction source code

  • bag._value0? (event)The callback to the event is performed first
  • judgebag._onlyFastPathBy default, the fast channel will be opened!
  • If you want to enable the slow channel, add it from the previous stepbagMatches are made one by one inside the packagepairs[i].value(event), and then gets back the closure call of the enclosing closure:element(event)

  • Here ifself._isDisposed || self._stoppedTrue returns an empty set, and there is no sequence of responses
  • in.completed, .errorWill change the stateself._stopped = trueThat is, the sequence cannot respond again after completion or error
  • in.completed, .errorIt also removes content added to the collection

In fact, if you understand the flow of the previous sequence, thissubjectI’m not talking about it anymore. It’s justsubjectThe subscription and response processes are implemented internally, so there is no need to introduce themsink

A variety of Subject

PublishSubject

It can be initialized without initialization (that is, null), and it will only send elements to the subscriber that were received after the subscription.

// PublishSubject // 1: initializes the sequence let publishSub = PublishSubject<Int>() // Initializes the sequence of PublishSubject with type Int // 2: sends the response sequence Publishsub. onNext(1) // 3: Subscribe sequence publishsub. subscribe {print(" Subscribe to :",$0)}. Disposed (by: Disposbag) // Send response publishsub.onNext (2) publishsub.onNext (3) /* Subscribed: next(2) subscribed: next(3) */Copy the code
  • Signal: 1.Can not be subscribed, only the response after the subscription is accepted

BehaviorSubject

This is created with a default initialization value. When a subscriber subscrires to a BehaviorSubject, it receives a BehaviorSubject Event emitted after the subscription, or a default value emitted if no data has been received. The new event is then received as normal as the PublishSubject.

Slightly different from the PublishSubject BehaviorSubject, this BehaviorSubject has a store function: it stores the last signal

Print ("**********BehaviorSubject**********") // BehaviorSubject // 1: Create a sequence let behaviorSub = behaviorSubject.init (value: 1) // 2: Signal behaviorSub.onNext(2) behaviorSub.onNext(3) // 3: Subscribe sequence behaviorSub.subscribe{print(" Subscribe :",$0)} .disposed(by: OnNext (4) behaviorSub.onNext(5) // Subscribe again behaviorSub.subscribe{print(" Subscribed :",$0)} Disposed (by: disposbag) / * * * * * * * * * * * BehaviorSubject * * * * * * * * * * subscribe to: next (3) subscribe to: next (4) subscribe to: next (5) subscribe to: next(5) */Copy the code
  • When no signal is available, it is sent by defaultSignal: 100
  • Only one signal can be stored:Signal 2Will beSignal 3cover
  • The ability to store signals before subscribing to them

  • Class with a property that holds a signal
  • Event response: The new event overwrites the original event
  • Other processes andpublishThe same

ReplaySubject

ReplaySubject sends all events of the source Observable whenever the Observer subscribes.

Print (" * * * * * * * * * * ReplaySubject * * * * * * * * * * ") / / ReplaySubject / / 1: create sequence let replaySub = ReplaySubject<Int>.create(bufferSize: 2) // Let replaySub = ReplaySubject<Int>. CreateUnbounded () // 2: send signals replaysub.onNext (1) replaysub.onnext (2) Replaysub. onNext(3) Replaysub. onNext(4) // 3: Subscribe replaysub. subscribe{print(" Subscribe to :",$0)}. Disposbag) // Replaysub.onNext (7) replaysub.onnext (8) replaysub.onnext (9) /* **********ReplaySubject********** Subscribed: next(3) subscribed: next(4) subscribed: next(7) subscribed: next(8) subscribed: next(9) */Copy the code
  • abufferSizeSpace, store as many responses as you want
  • calladdValueToBufferThe function adds the sent element toqueueIn the.
  • calltrimThe function to deletequeueIn more thanbufferSizeThe superfluous element of.
  • Other procedures remain the same
  • The source code is relative toBehaviorSubjectThe storage property of the

AsyncSubject

The AsyncSubject sends only the last event sent by the source Observable, and only after the source Observable has completed. (If the source Observable does not send any value, the AsyncSubject does not send any value either.)

Print (" * * * * * * * * * * AsyncSubject * * * * * * * * * * ") / / AsyncSubject / / 1: create sequence let asynSub = AsyncSubject < Int >. The init () / / 2: send a signal Asynsub. onNext(1) Asynsub. onNext(2) // 3: Subscribe asynsub. subscribe{print(" Subscribe to :",$0)}. OnNext (3) asynsub. onNext(4) asynsub. onError(nseror.init (domain: "PXWX ", code: 10086, the userInfo: nil)) asynSub. OnCompleted () / * * * * * * * * * * * AsyncSubject * * * * * * * * * * subscribe to: error(Error Domain=pxwx Code=10086 "(null)") */Copy the code

Variable

Variable deprecated, here is the code for you to encounter the old version! Because of the flexibility of this Variable, it is widely used in development.

print("**********Variable**********")
// Variable : 5.0已经废弃(BehaviorSubject 替换) - 这里板书 大家可以了解一下
// 1:创建序列
let variableSub = Variable.init(1)
// 2:发送信号
variableSub.value = 100
variableSub.value = 10
// 3:订阅信号
variableSub.asObservable().subscribe{ print("订阅到了:",$0)}
    .disposed(by: disposbag)
// 再次发送
variableSub.value = 1000
/*
**********Variable**********
订阅到了: next(10)
订阅到了: next(1000)
*/
Copy the code

BehaviorRelay

  • Replace the originalVariable
  • You can store a signal
  • Anytime subscribe response
  • Note when sending responses:behaviorR.accept(20)
print("**********BehaviorRelay**********") let behaviorRelay = BehaviorRelay(value: 61) behaviorRelay. Subscribe (onNext: {(num) in print(" Subscribe to :\(num)")}). Disposed (by: Disposbag) behaviorRelay. Accept (1000) /* ********** behaviorRelay ********** Subscribed :100 Subscribed :1000 Subscribed: completed */Copy the code

Sharing:Swift Information Download

Since the | address