使用ReactiveCocoa填补Swift中的KVO差距

您如何在Swift中进行键值观察? 你是否可以? 而仅使用Objective-C的本地KVO机制呢? 接下来是对ReactiveCocoa无名英雄的财产观察英雄的简要介绍: 财产 (和MutableProperty)。

马特·汤普森(Matt Thompson)在2013年为NSHipster详尽地解释了KVO的来龙去脉。 总而言之,我们只能说它是一个凌乱的Objective-C API,它今天仍然可以在Swift中使用。 除了您不能没有的场合(NSProgress有人吗?),我建议您不要使用它。 它的复杂性使其易于出错。 但是您说,Swift不提供本地等效功能……

我听到了您的声音,但假设您可以简单地执行以下操作,以侦听更改并作为响应重新加载表视图,以获取所有新项目:

 覆盖func viewDidLoad(){ 
super.viewDidLoad()
  viewModel.drafts.signal.observeValues {[弱自我]草稿在 
self?.tableView.reloadData()
}
}

符合ReactiveSwift属性

如果我忽略提及didSetwillSet属性观察器,那么我将忽略有关Swift的本机观察功能的重要提示 。 有了足够的样板代码,您绝对可以将类似于KVO的东西拼凑在一起。 例如,您可以使用didSet监听属性更改, 然后通过委托重新分配这些事件。 纯粹主义者将更喜欢这种方法,因为它不涉及任何魔术,也不需要第三方库。

但是,ReactiveSwift旨在通过称为Property的单个概念来封装所有这些复杂性。 很简单,因为在本质上,属性只是一个值框,可以将其更改通知其他人。 这是从ReactiveSwift的1.0版本中精简的协议:

 公共协议PropertyProtocol:类,BindingSourceProtocol { 
关联类型值

var值:值{get}
var生产者:SignalProducer {获取}
var signal:Signal {获取}
}

生产者和信号属性是您订阅的实际可观察​​值。 为什么要区分? RxJS README有一个不错的摘要:

冷的可观察对象在订阅时开始运行,即,可观察序列仅在调用Subscribe时才开始将值推入观察者。 值也不会在订户之间共享。 这与诸如鼠标移动事件或股票行情记录器之类的热观测值不同,这些事件甚至在订阅被激活之前就已经产生了价值。”

当应用于ReactiveSwift时,冷观测值对应于信号生成器,而热观测值则由“常规”信号表示。 在属性的上下文中,可以归结为:

  • 启动生产者将发出属性的初始值 ,以及所有后续更改;
  • 观察信号将仅发出观察开始后更改

用法

PropertyProtocol的具体实现包含在Property和MutableProperty类中。 通常,您将使用可变变量,因为它允许您更改属性的基础值,从而触发更改通知。 最简单的方法是放弃可选参数,而使用let常量代替:

  //定义属性 
let avatarUrl = MutableProperty(“ https://httpbin.org/image/jpeg”)
  //设置属性的值 
avatarUrl.value =“ ...”
  //侦听更改,但不包含初始值avatarUrl.signal.observeValues { 
...
}
  //侦听更改,包括初始值avatarUrl.producer.startWithValues { 
...
}

数据绑定

数据绑定是将属性绑定到UI组件的一种方法,这样,只要属性发生更改,该组件就会自动更新。 与AppKit相反,iOS的UIKit没有数据绑定的概念。 ReactiveCocoa通过单个自定义属性公开数据绑定:小于号后跟波浪号。

  <〜 

它的形状强调了绑定的单向性。 下面的示例清楚地说明了一个事实,即只要更改艺术家名称,就在艺术家标签的text属性上进行设置,而不是相反:

  //在控制器的viewDidLoad()中绑定绑定 
func viewDidLoad(){
super.viewDidLoad()
artistLabel.reactive.text <〜viewModel.artistName
}
  //此viewModel的示例实现(细节省略) 
类ViewModel {
让artistName = MutableProperty (无)
}

数据绑定是表达数据和UI组件之间关系的声明方式。 它减少了手动分配值的认知开销。 由于这种方法将绑定逻辑集中在一个地方,因此代码的位置也得到了改善。

活性可可粉

有什么不同? 借助ReactiveCocoa 5,核心团队决定拆分代码库,以便更清楚地描述每个组件的职责和范围。 该部门还允许框架用户更轻松地挑选他们在项目中需要的模块。

  • ReactiveSwift :街区上的新孩子。 这是反应式API的纯Swift实现。 它提供了所有的细节,包括信号,SignalProducers,属性,动作和绑定。
  • ReactiveObjC :ReactiveSwift基于Objective-C的同级。 这实质上是ReactiveCocoa 2.0,并保持在维护模式下。
  • ReactiveCocoa :UIKit和ReactiveSwift之间的连接部分。 它提供了UIKit组件的所有反应式扩展,并公开了它们的绑定目标。 它还引入了触发器,这是一种将Objective-C选择器转换为信号的方法。 您还可以将优质的ObjC KVO与信号包装在一起,以便它们可以与ReactiveSwift信号和生产者一起穿插。
  • ReactiveObjCBridge :将ReactiveCocoa 2.0 API与ReactiveSwift API桥接,因此ReactiveObjC仍可从Swift访问,从而实现与旧代码的互操作性。