ReactiveSwift(下)

SignalProducer

SignalProducer是ReactiveSwift中冷信号的落到实处, 是第二种发送事件的途径.

        热信号是移动着的事件发生器, 相对应的,
冷信号则是休眠中的事件产生器. 也正是说冷信号需求四个提醒操作,
然后才能发送事件, 而这一个提醒操作正是订阅它. 因为订阅后才发送事件, 显著,
冷信号不存在时机早晚的难题. 仍以春晚举例:

        冷信号也就是春晚的录制文件而不是现场直播, 通常情况下,
摄像文件肯定是不会自动播放的, 但你假若一双击,
它就被运行广播然后输出节目了.

//1. 通过SignalProducer.init(startHandler: (Observer, Lifetime) -> Void)创建SignalProducer

let producer = SignalProducer { (innerObserver, lifetime) in

lifetime.observeEnded({

print(“信号无效了 你能够在此间展开一些清理工科作”)

})

//2. 向外界发送事件

innerObserver.send(value: 1)

innerObserver.send(value: 2)

innerObserver.sendCompleted()

}

//3. 开立1个观望者封装事件处理逻辑

let outerObserver = Signal.Observer(value: { (value) in

print(“did received value: (value)”)

})

//4. 添加观看者到SignalProducer

producer.start(outerObserver)

输出: did received value: 1

did received value: 2

信号无效了 你能够在此处开展局地清理工科作

typealias Producer = ReactiveSwift.SignalProducer

let producer = Producer { (innerObserver, _) in

//没什么想清理的

innerObserver.send(value: 1)

innerObserver.send(value: 2)

innerObserver.sendCompleted()

}

producer.startWithValues { (value) in

print(“did received value: (value)”)

}

producer.startWithFailed(action: )

producer.startWithResult(action: )

producer.startWithXXX…各个方便人民群众函数

和Signal的订阅格局如出一辙, 只是名字换了须臾间,
Signal.observeXXX换到了SignalProducer.startXXX.

            都以事件产生器,
所以API方面Signal和SignalProducer都是同样的,上边包车型大巴map, on, merge,
comblinelast…等等, SignalProducer也有一份, 成效也都一致
,
小编就不多说了, 那里大致给两段代码说说或然遇到的坑

func fetchData(completionHandler: (Int, Error?) -> ()) {

print(“发起互连网请求”)

completionHandler(1, nil)

}

let producer = Producer {[unowned self] (innerObserver, _) in

self.fetchData(completionHandler: { (data, error) in

innerObserver.send(value: data)

innerObserver.sendCompleted()

})

}

producer.startWithValues { (value) in

print(“did received value: (value)”)

}

producer.startWithValues { (value) in

print(“did received value: (value)”)

}

输出: 发起网络请求

did received value: 1

发起网络请求

did received value: 1

莫不你只是想七个观看者共享1回网络请求带回的伊芙nt,
但事实上那里会产生四回网络请求, 但那不是3个bug, 那是两个feature.

SignalProducer的叁特本性是,
每便被订阅就会执行三回起先化时保留的闭包.

因而一旦你有相近1遍执行, 多处订阅的要求,
你应有选取Signal而不是SignalProducer. 所以, 符合要求的代码恐怕是如此:

let signalTuple = NSignal.pipe()

signalTuple.output.observeValues { (value) in

print(“did received value: (value)”)

}

signalTuple.output.observeValues { (value) in

print(“did received value: (value)”)

}

self.fetchData { (data, error) in

signalTuple.input.send(value: data)

signalTuple.input.sendCompleted()

}

输出: 发起网络请求

did received value: 1

did received value: 1

            到近日截至, 示例代码中给到的都是NoError类型的信号,
在实际开发中, 那鲜明是不容许的, 毕竟错误是不可防止的.
常常我们的门类会声可瑞康(Karicare)个类似APIError的谬误类型来代表这个不当,
所以你可能会有诸如此类的宣示:    

structAPIError: Swift.Error {

let code: Int

var reason =””

}

typealias NSignal = ReactiveSwift.Signaltypealias 

 APISignal = ReactiveSwift.Signaltypealias

 Producer = ReactiveSwift.SignalProducertypealias

 APIProducer = ReactiveSwift.SignalProducer

那般的声明很好, 能让ReactiveSwift写起来像OdysseyX斯维夫特一样”简洁”.
但此处必要添加下边包车型大巴代码才能更好的行事:

extension SignalProducer where Error == APIError {

@discardableResult

func startWithValues(_ action: @escaping (Value) -> Void) -> Disposable {

returnstart(Signal.Observer(value: action))

}

}

        那是因为暗中认可的SignalProducer是未曾startWithValues函数的,
Reactive斯威夫特会在Extension里给它足够startWithValues函数,
可是那只对NoError有效, 所以当您在自定义Error时, 请记得加上类似的代码.  
 

Observer

Observer消息的拍卖逻辑封装, Observer的根本代码如下:

//Observer.swift

public final class Observer {   

 public typealias Action = (Event) -> Void  

private let _send: Action            

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

public func send(_ event: Event) {        _send(event)    }                  

public func send(value: Value) {        _send(.value(value))    }                  
 

public func sendXXX() //其实都是send(_ event: Event)}

Observer内部维持了三个处理伊芙nt的闭包,
开始化Observer正是在设置这几个闭包,
而调用Observer.send则是在执行那个闭包.

**须求专注的点: Observer封装了伊芙nt的拍卖逻辑.
**


**Signal **

有了信息的载体和消息的处理逻辑, 接下来供给的是: 将音讯发送出去.

在Reactive斯威夫特中, 想要发送新闻共有八种途径, 那里大家先介绍第③种:
Signal.(事实上, 各种途径最后都以透过Signal来成功的, 所以, 其实唯有一种.)

Signal是Reactive斯维夫特中热信号的兑现, “热”的趣味是它是间接活动着的,
会主动将应运而生的事件伊夫nt向外发送, 而不会等到有人订阅后才开端发送.
这表示一旦订阅的机会晚于发送的机遇,
那么订阅者是不会接受订阅时机以前的风浪的.

举个栗子: 春晚现场直播从晚8点一贯播到12点,
那段时光出现的剧目正是Value事件, 12点一到出现的正是Completed事件.
很明显, 不管有没有人看春晚,  春晚现场都不关切, 节目来了就上,
时间一到就散. 但借使您想看直播, 最棒的机会当然是8点, 假设9点才打开TV,
那9点此前的剧目您肯定就失去了.

Signal的使用:

note: 那里的Value和Error都以泛型, 你需求在创建的时候实行点名

//public static func pipe(disposable: Disposable? = nil) -> (output: Signal, input: Observer)

let signalTuple = Signal.pipe()

let (signal, observer) = Signal.pipe()

见惯不惊, 你应有只通过Signal.pipe()函数来开端化3个热信号.
那个函数会回去四个元组, 元组的率先个值是output(类型为Signal),
第③个值是input(类型为Observer). 大家通过output来订阅信号,
通过input来向信号产生音讯.

亟需注意的点:
output的效用是治本信号状态并保留由订阅者提供的Observer对象(Observer._send封装了伊夫nt的拍卖逻辑),
而input的效应则是在吸纳到伊夫nt后相继执行那个被封存的Observer._send.

来看一段订阅Signal的基础代码:

func bindSignal2_1(){

//1.创建signal(output)和innerObserver(input)

let (signal, innerObserver) = Signal.pipe()

//2.创建Observer

let outerObserver1 = Signal.Observer(value: { (value) in

print(“did received value: (value)”)

})

//2.依然开创Observer

let outerObserver2 = Signal.Observer { (event) in

switch event {

case let .value(value):

print(“did received value: (value)”)

default: break }

}

signal.observe(outerObserver1)//3.向signal中添加Observer
signal.observe(outerObserver2)//3.还是向signal中添加Observer

innerObserver.send(value:
1)//4.向signal爆发音信(执行signal保存的兼具Observer对象的伊芙nt处理逻辑)

innerObserver.sendCompleted()//4.照旧执向signal爆发音信

}

        实际开发中我们必将不会如此写, 太繁琐了. 它的意义在于告诉各位:
1)每订阅叁次Signal实际上就是在向Signal中添加2个Observer对象.
2)尽管每一回订阅信号的拍卖逻辑都是相同的,
但它们仍旧是一心两样的的多个Observer对象.        

把地点的代码改的凝练一点:

typealias NSignal = ReactiveSwift.Signaloverride 

func viewDidLoad() {

        super.viewDidLoad() 

       //1.创建signal(output)和innerObserver(input)

        let (signal, innerObserver) = NSignal.pipe()

                         
 signal.observeValues { (value) in   //2&3.成立Observer并添加到Signal中            print(“did received value: (value)”)        }        signal.observeValues { (value) in   //2&3.照旧创办Observer并添加到Signal中            print(“did received value: (value)”)        }                 innerObserver.send(value: 1) //4. …        innerObserver.sendCompleted() //4. …}

        介绍下Signal.observeValues, 这是Signal.observe的二个便于函数,
作用是创办多少个
只处理Value事件的Observer并添加到Signal中,
类似的还有
只处理Failed事件的Signal.observeFailed和享有事件都能处理的**Signal.observeResult.

热信号相关代码:

typealias NSignal = ReactiveSwift.Signal

//ViewModel.swift

class ViewModel {

    let signal: NSignal    

    let innerObserver: NSignal.Observer       

    init() { (signal, innerObserver) = NSignal.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)//信号无效后发送事件    }

        view2的订阅时间晚于value1的发送时间,
所以view2收不到value1对应的事件,
那有的对应上边小编说的热信号并不关心订阅者的情形, 一旦有事件即会发送.

        第三某个则是Signal自己的性状:
收到任何非Value的风浪后信号便无效了.
所以您会看到即使view1和view2的订阅都早于value3的出殡时间,
但因为value3在信号发送前头阵送了completed事件,
所以view1和view2都不会接收value3事件, 同理,
view3也不会收取value3事件(它只会接受三个interrupted, 假使它关注的话).


KVO

public func signal(forKeyPath keyPath: String) -> Signal

tableView: UITableView

dynamic var someValue = 0

 reactive.signal(forKeyPath: “someValue”).observeValues { [weak self] (value) in      //code}

 tableView.reactive.signal(forKeyPath: “contentSize”).observeValues {[weak self] (contentSize) in

    if
 let contentSize = contentSize as? CGSize,        let strongSelf = self {

                 let isHidden = contentSize.height < strongSelf.tableView.height 

               
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now(),

               
execute: {            strongSelf.tableView.mj_footer.isHidden = isHidden

        })    }}

        KVO的Reactive版本, 对于NSObject的子类能够直接行使,
对于Swift的原生类供给添加dynamic修饰.


Map

let (signal, innerObserver) = NSignal.pipe()

signal.map { return “xxx” + String($0) } 

//map就不表明了

.observeValues { (value) in

            print(value)

        } 

        innerObserver.send(value: 1)innerObserver.sendCompleted()

打印:

xxx1


On:

public func on(

        event: ((Event) -> Void)? = nil,

        failed: ((Error) -> Void)? = nil, 

        completed: (() -> Void)? = nil,

        interrupted: (() -> Void)? = nil,

        terminated: (() -> Void)? = nil,  

       disposed: (() -> Void)? = nil,

        value: ((Value) -> Void)? = nil) -> Signal

D😈emo:

let (signal, innerObserver) = NSignal.pipe()

signal.on( value: { (value) in

    print(“on value: (value)”)

}).observeValues { (value) in

    print(“did received value: (value)”

)}

 innerObserver.send(value: 1)

innerObserver.sendCompleted()

 打印:

 on value: 1

  did received value: 1

        on: 在信号发送事件和订阅者收到事件之间插入一段事件处理逻辑,
你可以把它作为map的凝练版. (这一个函数的参数很多, 但暗中同意都有给nil,
所以你只须要关爱自个儿索要的一部分即可,
比如那里自身只想在Value事件间插入逻辑)


take(until:)

public func take(until trigger: Signal) -> Signal

let (signal, innerObserver) = NSignal.pipe()

let (takeSignal, takeObserver) = NSignal.pipe()signal.take(until: takeSignal).observeValues { (value) in

    print(“received value: (value)”)

}

 innerObserver.send(value: 1)

innerObserver.send(value: 2)

 takeObserver.send(value: ())

innerObserver.send(value: 3) 

takeObserver.sendCompleted()

innerObserver.sendCompleted()

 打印: received value: 1      received value: 2

        take(until:): 在takeSignal发送伊夫nt在此以前,
signal能够健康发送伊夫nt, 一旦takeSignal最首发送伊芙nt, signal就终止发送,
takeSignal也便是三个停下标志位.


take(first:)

publicfunc take(first count: Int) -> Signal

let (signal, innerObserver) = NSignal.pipe()

signal.take(first: 2).observeValues { (value) in

    print(“received value: (value)”)

}

innerObserver.send(value: 1)

innerObserver.send(value: 2)

innerObserver.send(value: 3)

innerObserver.send(value: 4)

innerObserver.sendCompleted()

打印: received value: 1   received value: 2

take(first:): 只取最初N次的伊芙nt.

好像的还有signal.take(last: ): 只取最终N次的伊芙nt.


参考资料:
ReactiveSwift(上)

Leave a Comment.