我正在尝试在我的新项目中使用 MVVM 模式。第一次,我创建了所有的视图模型来构建。但是,当我使用闭包实现异步业务逻辑(例如 fetchDataFromNetwork)时,闭包捕获旧视图模型值,然后更新为该值。不是新的视图模型值。
这是操场上的测试代码。
import Foundation
import XCPlayground
struct ViewModel {
var data: Int = 0
mutating func fetchData(completion:()->()) {
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
result in
self.data = 10
print("viewModel.data in fetchResponse : \(self.data)")
completion()
XCPlaygroundPage.currentPage.finishExecution()
}.resume()
}
}
class ViewController {
var viewModel: ViewModel = ViewModel() {
didSet {
print("viewModel.data in didSet : \(viewModel.data)")
}
}
func changeViewModelStruct() {
print("viewModel.data before fetch : \(viewModel.data)")
viewModel.fetchData {
print("viewModel.data after fetch : \(self.viewModel.data)")
}
}
}
var c = ViewController()
c.changeViewModelStruct()
控制台打印
viewModel.data before fetch : 0
viewModel.data in didSet : 0
viewModel.data in fetchResponse : 10
viewModel.data after fetch : 0
问题是 ViewController 中的视图模型没有新的值 10。
如果我将 ViewModel 更改为类,则不会调用 didSet,但 ViewController 中的视图模型具有新值 10。
你应该使用一个类。
如果您使用带有变异函数的结构,则该函数不应在闭包内执行变异;你应该not请执行下列操作:
struct ViewModel {
var data: Int = 0
mutating func myFunc() {
funcWithClosure() {
self.data = 1
}
}
}
如果我将 ViewModel 更改为类,则不会调用 didSet
这里没有任何问题 - 这是预期的行为。
如果您喜欢使用struct
, 你可以做
func fetchData(completion: ViewModel ->()) {
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
result in
var newViewModel = self
newViewModel.data = 10
print("viewModel.data in fetchResponse : \(self.data)")
completion(newViewModel)
XCPlaygroundPage.currentPage.finishExecution()
}.resume()
}
viewModel.fetchData { newViewModel in
self.viewModal = newViewModel
print("viewModel.data after fetch : \(self.viewModel.data)")
}
另请注意,关闭提供给dataTaskWithURL
不在主线程上运行。您可能想打电话dispatch_async(dispatch_get_main_queue()) {...}
in it.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)