ReactiveSwift框架分析1 — Event,Observer,Signal

本篇文章主要讲一下ReactiveSwift中的核心元件:

  • Event
  • Observer
  • Signal

1. Event

一个按钮被按下了、调用API接收到了一条信息或是一次长时间操作的完成,都会产生了Event,并通过信号发送它们给了观察者,每个信息的载体(value/error)对应的是一个枚举Event:

public enum Event {
        /// A value provided by the signal.
        case value(Value)

        /// The signal terminated because of an error. No further events will be
        /// received.
        case failed(Error)

        /// The signal successfully terminated. No further events will be received.
        case completed

        /// Event production on the signal has been interrupted. No further events
        /// will be received.
        ///
        /// - important: This event does not signify the successful or failed
        ///              completion of the signal.
        case interrupted
}

Note: interrupted表示事件被打断, 除非你去订阅一个已经无效的信号, 否则这个状态不会出现,当信号发送非Value的Event时, 那么这个信号就无效了. 无效的原因可能是failed, completed, interrupted。

2. Observer

An Observer is a simple wrapper around a function which can receive Events.

Observer可以是任意东西,只要它正在等待或者即将等待信号中的事件。在 RAC中,它是通过使用基于闭包的 Signal.observe方式或者是 SignalProducer.start方式隐式创建的,Observer封装了Event的处理逻辑,能接收Events:

public final class Observer {
        public typealias Action = (Event) -> Void
        private let _send: Action

                /// Whether the observer should send an `interrupted` event as it deinitializes.
        private let interruptsOnDeinit: Bool

        internal init(action: @escaping Action, interruptsOnDeinit: Bool) {
            self._send = action
            self.interruptsOnDeinit = interruptsOnDeinit
        }

    public init(_ action: @escaping Action) {
            self._send = action
            self.interruptsOnDeinit = false
    }

        public func send(_ event: Event) {
            _send(event)
        }
        public func send(value: Value) {
            _send(.value(value))
        }
       public func send(error: Error) {
            _send(.failed(error))
        }
       public func sendInterrupted() {
            _send(.interrupted)
        }
        
}

分析源码可以看出,Observer内部有一个处理Event的闭包_send,在初始化Observer的时候就是给这个闭包赋值,而调用Observer.send则是在执行这个闭包。

有了信息的载体和信息的处理逻辑, 接下来需要的是将信息发送出去:Signal。

3. Signal

Signal是热信号,会主动将产出的事件Event向外发送,而不会等到有人订阅后才开始发送,Signal源码包含一个Core属性,Signal只是Core的一个壳,所以我们主要分析Core的源码:

private let core: Core

private final class Core {
        private let disposable: CompositeDisposable
        private let stateLock: Lock 
        private let sendLock: Lock 
                private var state: State 
        ......
}

private enum State {
        case alive(Bag<Observer>, hasDeinitialized: Bool)
        case terminating(Bag<Observer>, TerminationKind)
        case terminated
}

Core里面最重要的属性就是StateState的作用有两个:

  • 指示信号的状态。
  • 保存信号订阅者添加进来的Observer对象。

Observer对象是怎么被添加进来的呢?先看下源码:

fileprivate func observe(_ observer: Observer) -> Disposable? {
            var token: Bag<Observer>.Token?

            stateLock.lock()
                       //1.信号处于state.alive状态,将新的observer对象添加到state.alive的数组中
            if case let .alive(observers, hasDeinitialized) = state {
                var newObservers = observers
                token = newObservers.insert(observer)
                self.state = .alive(newObservers, hasDeinitialized: hasDeinitialized)
            }

            stateLock.unlock()
                        
                        //2. 如果1顺利执行,token会被赋值(即信号处于alive状态) 返回一个Disposable对象 否则直接向observer对象发 送interrupted事件
            if let token = token {
                return AnyDisposable { [weak self] in
                    self?.removeObserver(with: token)
                }
            } else {
                observer.sendInterrupted()
                return nil
            }
        }

从源码我们可以看出,通过observe方法添加并保存了Observer(也就是保存了Event的处理逻辑),接下来需要的就是在合适的时机执行这些Observer内部的处理逻辑,就要通过调用Core.send(_ event: Event)方法,具体看以下源码:

private func send(_ event: Event) {
            if event.isTerminating { // 收到非Value的Event,信号状态从.alive切换到.terminating

                self.stateLock.lock()

                                //  将.alive中的Observer数组移到.terminating中,遍历. terminating的数组observers,调用send函数
                if case let .alive(observers, _) = state {
                    self.state = .terminating(observers, .init(event))
                    self.stateLock.unlock()
                } else {
                    self.stateLock.unlock()
                }

                tryToCommitTermination()
            } else { // 收到Value的Event
                self.sendLock.lock()
                self.stateLock.lock()

                                //遍历.alive的数组observers,调用send函数
                if case let .alive(observers, _) = self.state {
                    self.stateLock.unlock()

                    for observer in observers {
                        observer.send(event)
                    }
                } else {
                    self.stateLock.unlock()
                }

                self.sendLock.unlock()

                stateLock.lock()

                                //遍历. terminating的数组observers,调用send函数
                if case .terminating = state {
                    stateLock.unlock()
                    tryToCommitTermination()
                } else {
                    stateLock.unlock()
                }
            }
}

private func tryToCommitTermination() {
    ...lock部分代码 略
    if case let .terminating(observers, terminationKind) = state {

        //切换状态到.terminated,遍历. terminating的数组observers,调用send函数
        state = .terminated
        if let event = terminationKind.materialize() {
            for observer in observers {
                observer.send(event)
            }
        }
    }
}

有关信号状态的切换state,它确切来说是一个枚举:

private enum State {
        case alive(Bag<Observer>, hasDeinitialized: Bool)
        case terminating(Bag<Observer>, TerminationKind)
        case terminated
        ......
}

其中,状态terminated是不带关联数组的,这意味着当信号切换到terminated状态时,那么那些被保存的Observer对象也就跟着释放了,所以当不再需要使用信号时,应该向信号发送一个非Value事件确保资源释放。

那有了Observer的添加,Observer.send的执行, 再通过Signal.pipe()方法创建一个热信号将这一切连接起来了,这个函数会返回一个元组, 元组的第一个值是output(类型为Signal), 第二个值是input(类型为Observer). 我们通过output来订阅信号, 通过input来向信号发生信息。

public static func pipe(disposable: Disposable? = nil) -> (output: Signal, input: Observer) {
    var observer: Observer!
    
    let signal = self.init { innerObserver, lifetime in
        observer = innerObserver
        lifetime += disposable
    }
    return (signal, observer)
}
//Signal.init()
public init(_ generator: (Observer, Lifetime) -> Void) {
     core = Core(generator)
}

//Core.init()
fileprivate init(_ generator: (Observer, Lifetime) -> Void) {
    
    //1. 设置信号初始状态为alive 同时初始化alive中的数组
    state = .alive(Bag(), hasDeinitialized: false)

    ......
   
    //2. 创建一个Observer对象并将该对象的_send闭包设置为Core.send函数
    generator(Observer(action: self.send, interruptsOnDeinit: true), Lifetime(disposable))
}

从源码可以看出, pipe()函数会通过一个generator: (Observer, Lifetime)闭包去创建Core对象, 然后通过这个Core对象去创建Signal,pipe()函数通过generator闭包捕获了Core.init()中的innerObserver对象, 而这个InnerObserver对象的_send指向的其实是Core.send函数. 最后pipe()将返回Signal和InnerObserver。

所以,pipe().output(即Signal)的作用是管理信号状态并保存由订阅者提供的Observer对象, 而pipe().input(即InnerObserver)的作用则是在接收到Event后依次执行这些被保存的Observer._send

上面的流程可以表示如下:

1477238-c53f4c91e78a6c76.png
流程

上面我们分析了Signal源码,接下来我们来具体创建一下Signal,对它进行使用。

Signal的使用

上面讲过,通过Signal.pipe()函数会返回一个元组,元组的第一个值是output(类型为Signal),第二个值是input(类型为Observer),我们通过output来订阅信号, 通过input来向信号发生信息。

let signalTuple = Signal<Int, NoError>.pipe()
let (signal, observer) = Signal<Int, NoError>.pipe()

我们在viewDidLoad中创建一个热信号,并发送数据:

typealias NSignal<T> = ReactiveSwift.Signal<T, NoError>
override func viewDidLoad() {
        super.viewDidLoad()
        //创建signal(output)和innerObserver(input)
        let (signal, innerObserver) = NSignal<Int>.pipe()
        
        signal.observeValues { (value) in   //创建Observer并添加到Signal中
            print("did received value: \(value)")
        }
        signal.observeValues { (value) in   //再次创建Observer并添加到Signal中
            print("did received value: \(value)")
        }
        
        innerObserver.send(value: 1) 
        innerObserver.sendCompleted() 
}
//输出结果:  did received value: 1
                     did received value: 1

Signal.observeValues,是Signal.observe的一个便利函数, 作用是创建一个只处理Value事件的Observer并添加到Signal中, 类似的还有只处理Failed事件的Signal.observeFailed和所有事件都能处理的Signal.observeResult。

再来看一个ViewModel中的Demo:

typealias NSignal<T> = ReactiveSwift.Signal<T, NoError>
//ViewModel.swift
class ViewModel {
    let signal: NSignal<Int>
    let innerObserver: NSignal<Int>.Observer
    
    init() { (signal, innerObserver) = NSignal<Int>.pipe() }
}

//View1.swift
class View1 {
    func bind(viewModel: ViewModel) {
        viewModel.signal.observeValues { (value) in
            print("View1 received value: \(value)")
        }
    }
}

//View2.swift
class View2 {
    func bind(viewModel: ViewModel) {
        viewModel.signal.observeValues { (value) in
            print("View2 received value: \(value)")
        }
    }
}

//View3.swift
class View3 {
    func bind(viewModel: ViewModel) {
        viewModel.signal.observeValues { (value) in
            print("View3 received value: \(value)")
        }
        viewModel.signal.observeInterrupted {
            print("View3 received interrupted")
        }
    }
}

override func viewDidLoad() {
        super.viewDidLoad()
        
        let view1 = View1()
        let view2 = View2()
        let view3 = View3()
        let viewModel = ViewModel()

        view1.bind(viewModel: viewModel)//订阅时机较早
        viewModel.innerObserver.send(value: 1)

        view2.bind(viewModel: viewModel)//订阅时机较晚
        viewModel.innerObserver.send(value: 2)
        viewModel.innerObserver.sendCompleted()//发送一个非Value事件 信号无效
        
        view3.bind(viewModel: viewModel)//信号无效后才订阅
        viewModel.innerObserver.send(value: 3)//信号无效后发送事件
    }
输出: View1 received value: 1
      View1 received value: 2
      View2 received value: 2
      View3 received interrupted

view2的订阅时间晚于value1的发送时间,所以view2收不到value1对应的事件,而之后发送一个非Value的事件后,信号便无效了。所以虽然view1和view2的订阅都早于value3的发送时间,但因为value3在信号发送前先发送了completed,结果就是view1和view2都不会收到value3事件,当然view3也不会收到value3事件,它只会收到一个interrupted。

猜你喜欢

转载自blog.csdn.net/weixin_34360651/article/details/90812078
今日推荐