我使用Model View ViewModel範例開發iOS應用程序來構建視圖控制器並表示其數據。這與ReactiveCocoa結合是一個強大的工具;視圖控制器變得越來越臃腫,視圖模型更容易測試,並且存在明顯的關注點分離。MVVM通用網絡體系結構
我對這個特定架構的一個問題是,像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")
它並不能完全解決視圖控制器和視圖模型應該如何相互交互的問題,但它絕對會將網絡代碼移動到單個故障點。
我不同意,因爲模型應該只是一個數據表示。儘管它可以工作,但只要數據獲取方法是類方法,而不是實例方法。 – barndog
我在考慮像PostSearch這樣的模型,它有網絡代碼,而不是Post模型也應該包含網絡代碼。 – Ionut