美文网首页
ReactiveSwift框架分析4 — Property和Mu

ReactiveSwift框架分析4 — Property和Mu

作者: 沈枫_ShenF | 来源:发表于2019-06-06 17:01 被阅读0次

这篇文章来总结下Property和MutableProperty。

Property

属性是一个可观察的容器,每当它的值被更改时,它就会发出它的值。它遵守PropertyProtocol协议,本身具有以下属性:

  • value: 表示当前值。
  • producer: 一个发送处在变化中的当前值的SignalProducer。
  • signal: 发送连续变化的信号,不发送当前值。

它有什么用呢?

当我们只需要处理值而不是错误时,可以用Property。还是举个例子吧:

每隔5秒打印一条消息。

第一步,创建signalProducer:

let signalProducer: SignalProducer<Int, NoError> = SignalProducer { (observer, lifetime) in
    let now = DispatchTime.now()
    for index in 0..<10 {
        let timeElapsed = index * 5
        DispatchQueue.main.asyncAfter(deadline: now + Double(timeElapsed))
                {
            guard !lifetime.hasEnded else {
                observer.sendInterrupted()
                return
            }
            observer.send(value: timeElapsed)
            if index == 9 {
                observer.sendCompleted()
            }
        }
    }
}

Note:这里的错误类型时NoError,我们不用处理错误,可以很好地用Property来封装。

第二步,创建Property:

let property = Property(initial: 0, then: signalProducer)

这里,我们给了初始值0,上面讲过Property包含一个signal和producer,signal不发送当前值,仅仅发送值的连续变化。

第三步,使用property的producer启动执行:

property.producer.startWithValues { value in
    print("[Observing SignalProducer] Time elapsed = \(value)")
}

最终输出:

[Observing SignalProducer] Time elapsed = 0
[Observing SignalProducer] Time elapsed = 0
[Observing SignalProducer] Time elapsed = 5
[Observing SignalProducer] Time elapsed = 10
[Observing SignalProducer] Time elapsed = 15
[Observing SignalProducer] Time elapsed = 20
[Observing SignalProducer] Time elapsed = 25
[Observing SignalProducer] Time elapsed = 30
[Observing SignalProducer] Time elapsed = 35
[Observing SignalProducer] Time elapsed = 40
[Observing SignalProducer] Time elapsed = 45

第四步,使用property的signal启动执行:

property.signal.observeValues { value in
    print("[Observing Signal] Time elapsed = \(value)")
}

最终输出:

[Observing Signal] Time elapsed = 0
[Observing Signal] Time elapsed = 5
[Observing Signal] Time elapsed = 10
[Observing Signal] Time elapsed = 15
[Observing Signal] Time elapsed = 20
[Observing Signal] Time elapsed = 25
[Observing Signal] Time elapsed = 30
[Observing Signal] Time elapsed = 35
[Observing Signal] Time elapsed = 40
[Observing Signal] Time elapsed = 45

上面这个例子,signal没有把初始值打印出来,我们创建了一个通过SignalProducer来获取值的Property,其实也可以创建一个通过Signal来获取值的property。

MutableProperty

MutableProperty是一个可观察的容器,它像属性一样在更改时发出值,但也可以直接修改值。和Property一样,它也遵循propertyprotocol协议。

举个例子吧。

第一步,给个初始值创建mutableProperty:

let mutableProperty = MutableProperty(1)

第二步,修改value:

mutableProperty.value = 3

第三步,绑定

mutableProperty <~ signalProducer

Property/MutableProperty发送事件,从冷热信号的定义上来看, Property的行为应该属于热信号, 但和上文的Signal不同, Property/MutableProperty只提供一种状态的事件: Value(虽然它有Completed状态)。

Property/MutableProperty对比使用

首先,看Property:

let constant = Property(value: 1)
// constant.value = 2  // error: Property(value)创建的value不可变

constant.producer.startWithValues { (value) in
    print("producer received: (value)")
}
 
//并不会被触发,所以不会打印
constant.signal.observeValues { (value) in
    print("signal received: (value)")
}

最终输出:

     producer received: 1

可以看出,signal并没有被触发,这个和上面的例子不同之处在于:上面的Property跟一个SignalProducer绑定,接管了值的变化,所以上面的例子中的signal可以被触发。

其次,看MutableProperty:

let mutableProperty = MutableProperty(1)
 
 //冷信号可以收到初始值value=1和2,3 
mutableProperty.producer.startWithValues {
    print("producer received ($0)")
}
 
 //冷信号可以收到初始值value=1和2,3 
mutableProperty.signal.observeValues { 
    print("signal received ($0)")
}
 
mutableProperty.value = 2 
mutableProperty.value = 3 

最终输出:

 producer received: 1
 producer received: 2
 signal received: 2
 producer received: 3
 signal received: 3

可以看出,由于producer是冷信号,前后的事件都能接收到,而signal是热信号,只能接收到后来的事件,而且Property值的每次更改设置就是在发送Value事件。

综上所述:

  1. Property.value不可设置,MutableProperty.value可设置。
  2. Property/MutableProperty内部有一个Producer和一个Signal,设置value即是在向这两个信号发送Value事件。

最后,来个实例展示

再来看个具体的手机号输入限制的实例,要求是:

  1. 用户输入手机号,限制手机号最多输入11个数字。
  2. 验证手机号是否有效,手机号无效需要展示错误信息。
let errorLabel: UILabel 
let sendButton: UIButton
let phoneNumerTextField: UITextField

var errorText = MutableProperty("")
var validPhoneNumer = MutableProperty("")

//进行一系列绑定
errorLabel.reactive.text <~ errorText 
sendButton.reactive.isEnabled <~ errorText.map{ $0.count == 0 } 
sendButton.reactive.backgroundColor <~ errorText.map{ $0.count == 0 ? UIColor.red : UIColor.gray } 
phoneNumerTextField.reactive.text <~ validPhoneNumer 

//有效输入的数据来自输入框输入变化
validPhoneNumer <~ phoneNumerTextField.reactive.continuousTextValues
    .map({(text) -> String in
        
    let phoneNumer = (text ?? "").substring(to: 11) 
   
    //检查手机格式是否正确
    let isValidPhoneNum = NSPredicate(format: "SELF MATCHES %@", "^1(3[0-9]|5[0-35-9]|8[025-9])\d{8}$").evaluate(with: phoneNumer) 

    errorText.value = isValidPhoneNum ? "手机号格式不正确" : "" 
    return phoneNumer 
})

相关文章

网友评论

      本文标题:ReactiveSwift框架分析4 — Property和Mu

      本文链接:https://www.haomeiwen.com/subject/yspuxctx.html