如何在 ReactiveCocoa 3 和 4 中进行基本绑定
How to make basic bindings in ReactiveCocoa 3 and 4
我最近一直在阅读有关 ReactiveCocoa v3 的资料,但我正在为设置基本内容而苦苦挣扎。我已经阅读了变更日志、测试、少数 SO 问题以及 Colin Eberhardt 就该主题撰写的文章。但是,我仍然缺少有关基本绑定的示例。
假设我有一个显示当天菜单的应用程序。该应用程序使用 RAC3 和 MVVM 模式。
型号(菜单)
该模型有一种获取今天菜单的简单方法。至于现在,这不做任何网络请求,它基本上只是创建一个模型对象。 mainCourse
属性 是 String
.
class func fetchTodaysMenu() -> SignalProducer<Menu, NoError> {
return SignalProducer {
sink, dispoable in
let newMenu = Menu()
newMenu.mainCourse = "Some meat"
sendNext(sink, newMenu)
sendCompleted(sink)
}
}
视图模型(菜单视图模型)
视图模型公开了不同的 String
变量来让视图控制器显示菜单。我们就加一个属性来展示主菜吧。
var mainCourse = MutableProperty("")
然后我们为此添加绑定 属性:
self.mainCourse <~ Menu.fetchTodaysMenu()
|> map { menu in
return menu.mainCourse!
}
ViewController(菜单ViewController)
最后但同样重要的是,我想在视图中展示这门主菜。我会为此添加一个UILabel
。
var headline = UILabel()
最后我想通过观察我的视图模型来设置那个 UILabel 的 text
属性。 喜欢:
self.headline.text <~ viewModel.headline.producer
不幸的是,这不起作用。
问题
- 方法
fetchTodaysMenu()
return 是 SignalProducer<Menu, NoError>
,但是如果我想让这个方法变成 return SignalProducer<Menu, NSError>
怎么办?这将使我在视图模型中的绑定失败,因为该方法现在可能 return 出错。我该如何处理?
- 如前所述,我的视图控制器中的当前绑定不起作用。我一直在尝试创建一个
MutableProperty
来表示 UILabel
的 text
属性,但我从来没有做对。我还认为必须为每个我想绑定的 属性 创建额外的变量感觉笨拙或冗长。这在 RAC2 中是不需要的。我也有意尝试避免使用 DynamicProperty
,但也许我不应该这样做?我基本上只是想找到正确的做法 RAC(self.headline, text) = RACObserve(self.viewModel, mainCourse);
.
非常感谢任何其他关于如何进行此基本设置的 feedback/guidance。
因此,在写完这个问题后,Colin Eberhardt 制作了他的 RAC3 博客 post 系列的第 3 部分,其中包括一个有趣且非常相关的使用 MVVM 和 RAC3 的示例。 post 可以找到 here and the source code here.
根据他的工作,我已经设法回答了我自己的问题:
通过采用稍微不同的方法,我可以根据需要将 fetchTodaysMenu()
return 设为 SignalProducer<Menu, NSError>
。下面是我在我的视图模型中所做的事情:
MenuService.fetchTodaysMenu()
|> observeOn(QueueScheduler.mainQueueScheduler)
|> start(next: { response in
self.mainCourse.put(response.mainCourse!)
}, error: {
println("Error \([=10=])")
})
在 RAC3 beta 4 中似乎还没有 UIKit
绑定。Colin 自己做了一些 UIKit
扩展来帮助他制作我也在寻找的这些绑定.这些可以找到 here。将它们添加到我的项目中,使我能够做我想做的事:
self.mainCourse.rac_text <~ self.viewModel.mainCourse
2015 年 5 月 25 日更新
在使用 ReactiveCocoa 3 进行了大量工作之后,我想再次回答 1)。通过使用 catch
,可以以更明确的方式执行此操作。我最终为此实现了一个小的辅助函数:
public func ignoreError<T: Any, E: ErrorType>(signalProducer: SignalProducer<T, E>) -> SignalProducer<T, NoError> {
return signalProducer
|> catch { _ in
SignalProducer<T, NoError>.empty
}
}
该函数将任何 NSError
转换为 NoError
,从而可以通过 MenuService.fetchTodaysMenu() |> ignoreError
.
进行绑定
我开源了我的项目,因为这对于其他研究 ReactiveCocoa 3.0 的人来说可能是一个很好的起点:
https://github.com/s0mmer/TodaysReactiveMenu
2016 年 3 月 5 日更新
正如评论中突出显示的那样,自 Swift 2 起,ignoreError
函数现在看起来像:
public func ignoreError() -> SignalProducer<Value, NoError> {
return flatMapError { _ in
SignalProducer<Value, NoError>.empty
}
}
此外,还制作了一个名为 Rex 的扩展库,其中添加了类似的内容。
我最近一直在阅读有关 ReactiveCocoa v3 的资料,但我正在为设置基本内容而苦苦挣扎。我已经阅读了变更日志、测试、少数 SO 问题以及 Colin Eberhardt 就该主题撰写的文章。但是,我仍然缺少有关基本绑定的示例。
假设我有一个显示当天菜单的应用程序。该应用程序使用 RAC3 和 MVVM 模式。
型号(菜单)
该模型有一种获取今天菜单的简单方法。至于现在,这不做任何网络请求,它基本上只是创建一个模型对象。 mainCourse
属性 是 String
.
class func fetchTodaysMenu() -> SignalProducer<Menu, NoError> {
return SignalProducer {
sink, dispoable in
let newMenu = Menu()
newMenu.mainCourse = "Some meat"
sendNext(sink, newMenu)
sendCompleted(sink)
}
}
视图模型(菜单视图模型)
视图模型公开了不同的 String
变量来让视图控制器显示菜单。我们就加一个属性来展示主菜吧。
var mainCourse = MutableProperty("")
然后我们为此添加绑定 属性:
self.mainCourse <~ Menu.fetchTodaysMenu()
|> map { menu in
return menu.mainCourse!
}
ViewController(菜单ViewController)
最后但同样重要的是,我想在视图中展示这门主菜。我会为此添加一个UILabel
。
var headline = UILabel()
最后我想通过观察我的视图模型来设置那个 UILabel 的 text
属性。 喜欢:
self.headline.text <~ viewModel.headline.producer
不幸的是,这不起作用。
问题
- 方法
fetchTodaysMenu()
return 是SignalProducer<Menu, NoError>
,但是如果我想让这个方法变成 returnSignalProducer<Menu, NSError>
怎么办?这将使我在视图模型中的绑定失败,因为该方法现在可能 return 出错。我该如何处理? - 如前所述,我的视图控制器中的当前绑定不起作用。我一直在尝试创建一个
MutableProperty
来表示UILabel
的text
属性,但我从来没有做对。我还认为必须为每个我想绑定的 属性 创建额外的变量感觉笨拙或冗长。这在 RAC2 中是不需要的。我也有意尝试避免使用DynamicProperty
,但也许我不应该这样做?我基本上只是想找到正确的做法RAC(self.headline, text) = RACObserve(self.viewModel, mainCourse);
.
非常感谢任何其他关于如何进行此基本设置的 feedback/guidance。
因此,在写完这个问题后,Colin Eberhardt 制作了他的 RAC3 博客 post 系列的第 3 部分,其中包括一个有趣且非常相关的使用 MVVM 和 RAC3 的示例。 post 可以找到 here and the source code here.
根据他的工作,我已经设法回答了我自己的问题:
通过采用稍微不同的方法,我可以根据需要将
fetchTodaysMenu()
return 设为SignalProducer<Menu, NSError>
。下面是我在我的视图模型中所做的事情:MenuService.fetchTodaysMenu() |> observeOn(QueueScheduler.mainQueueScheduler) |> start(next: { response in self.mainCourse.put(response.mainCourse!) }, error: { println("Error \([=10=])") })
在 RAC3 beta 4 中似乎还没有
UIKit
绑定。Colin 自己做了一些UIKit
扩展来帮助他制作我也在寻找的这些绑定.这些可以找到 here。将它们添加到我的项目中,使我能够做我想做的事:self.mainCourse.rac_text <~ self.viewModel.mainCourse
2015 年 5 月 25 日更新
在使用 ReactiveCocoa 3 进行了大量工作之后,我想再次回答 1)。通过使用 catch
,可以以更明确的方式执行此操作。我最终为此实现了一个小的辅助函数:
public func ignoreError<T: Any, E: ErrorType>(signalProducer: SignalProducer<T, E>) -> SignalProducer<T, NoError> {
return signalProducer
|> catch { _ in
SignalProducer<T, NoError>.empty
}
}
该函数将任何 NSError
转换为 NoError
,从而可以通过 MenuService.fetchTodaysMenu() |> ignoreError
.
我开源了我的项目,因为这对于其他研究 ReactiveCocoa 3.0 的人来说可能是一个很好的起点: https://github.com/s0mmer/TodaysReactiveMenu
2016 年 3 月 5 日更新
正如评论中突出显示的那样,自 Swift 2 起,ignoreError
函数现在看起来像:
public func ignoreError() -> SignalProducer<Value, NoError> {
return flatMapError { _ in
SignalProducer<Value, NoError>.empty
}
}
此外,还制作了一个名为 Rex 的扩展库,其中添加了类似的内容。