我使用Model View ViewModel范型开发iOS应用程序,以构造视图控制器并表示它们的数据。与ReactiveCocoa结合使用是一个强大的工具;视图控制器变得不那么臃肿,视图模型更容易测试,并且有明确的关注点分离。
我在这个特殊的架构中遇到的一个问题是,像MVC一样,仍然没有一个清晰的地方或方法来组织网络代码。举个简单的例子:
class HomepageViewModel {
var posts: MutableProperty<[Post]> = MutableProperty([])
func fetchPosts() -> SignalProducer<[Post], NSError> {
return SignalProducer { observer, disposable in
// do some networking stuff
let posts = ....
observer.sendNext(posts)
observer.sendCompleted()
}
}
}然后在我的视图控制器中,我可以这样做:
self.viewModel.posts <~ self.viewModel.fetchPosts().on(next: { _ in self.collectionView.reloadData() })对我来说,使用MVVM的整个目的是不将视图和视图控制器(我称之为视图表示层)暴露给任何网络代码,但我仍然需要一种方法来观察新内容已经被获取,而不知道细节,只是成功获取发生了。我想它看起来应该是这样的:
self.viewModel.contentUpdatedSignal.observeNext { _ in self.collectionView.reloadData() }同时,我也不想失去在使用<~时将信号和信号生成器绑定到可变属性的能力。
class ViewModel {
let someProperty = MutableProperty<[SomeModel]>([])
var (contentUpdatedSignal, observer) = Signal.pipe()
init() {
self.someProperty <~ self.fetchContent().on(next: { _ in observer.sendNext() }
}
func fetchContent() -> SignalProducer<[SomeModel], NSError> {
// do some fun stuff
}
}这样做的方法要好一些,但它仍然使用副作用来发送信号观察器上的下一个事件,如果您正在使用通用的ViewModel基类,则必须公开该观察器,以便子类可以使用它。
我正在寻找任何可以对MVVM体系结构进行改进的地方,要么对体系结构本身进行更改,使其不再是MVVM,并以更好、更通用的方式促进联网,要么甚至为视图模型制定某种通用的基础协议,将整个过程抽象化。
对我来说,在尽可能少公开视图模型信息的同时尽可能保持通用性是关键。理想情况下,我希望每个视图控制器与视图模型的交互方式与网络的工作方式完全相同。
编辑:
根据@lonut的建议,我将一些网络代码移动到我的模型类中,但仅作为静态方法:
import Foundation
import ReactiveCocoa
import Moya
protocol RESTModel {
typealias Model
static func create(parameters: [NSObject: AnyObject]?) -> SignalProducer<Model, Moya.Error>
static func find() -> SignalProducer<Model, Moya.Error>
static func get(id: String) -> SignalProducer<Model, Moya.Error>
static func update(id: String) -> SignalProducer<Model, Moya.Error>
static func remove(id: String) -> SignalProducer<Model, Moya.Error>
}
extension RESTModel {
static func create(parameters: [NSObject: AnyObject]? = nil) -> SignalProducer<Self.Model, Moya.Error> {
return SignalProducer.empty
}
static func find() -> SignalProducer<Self.Model, Moya.Error> {
return SignalProducer.empty
}
static func get(id: String) -> SignalProducer<Self.Model, Moya.Error> {
return SignalProducer.empty
}
static func update(id: String) -> SignalProducer<Self.Model, Moya.Error> {
return SignalProducer.empty
}
static func remove(id: String) -> SignalProducer<Self.Model, Moya.Error> {
return SignalProducer.empty
}
}通过这种方式,模型可以随意实现网络调用,其好处是抽象出实现细节,如特定Moya网络调用、响应对象的映射等。
假设你有一个User模型:
User.get("myUserID")它没有完全解决视图控制器和视图模型应该如何相互交互的问题,但它确实将网络代码移到了单点故障。
发布于 2016-03-08 20:34:22
我在使用MVVM或RAC方面不是很高级,但从我使用的网络代码来看,应该是在模型部分,然后是在视图模型部分观察结果的方法(类似于" fetchPosts ()"),并且在视图部分调用fetchPosts方法。我推荐你使用this blog post获取更多信息。
https://stackoverflow.com/questions/35866725
复制相似问题