【发布时间】:2020-08-26 16:36:25
【问题描述】:
拥有一个由 Xcode 生成的 SwiftUI 项目,并添加一个带有 MyViewModel 的自定义 MyView。
ContentView 只是渲染 MyView。
问题:
- 当
ContentView重新加载(重新加载按钮改变其状态)时,MyViewModel与MyView断开连接(当单击按钮时,MyView计数器在 UI 中停止递增),但控制台日志显示增量工作。 - 如果模型订阅了发布者,它不会因为实例未发布而被取消订阅。因此,实例仍会处理传入消息并更改应用的数据和状态。
在控制台中查看实例计数器和内存地址:
- 每次刷新
ContentView时,都会创建一个新的MyView和MyViewModel实例。但是,计数器增量使用最初创建的模型实例。 - 部分模型实例未发布。
编辑: 每次重新创建 MyView 时都需要重新创建模型。
import SwiftUI
struct ContentView: View {
@State
private var reloadCounter = 0
var body: some View {
VStack {
Button(action: { self.reloadCounter += 1 },
label: { Text("Reload view") })
Text("Reload counter: \(reloadCounter)")
MyView().environmentObject(MyViewModel())
}
}
}
import SwiftUI
struct MyView: View {
@EnvironmentObject
private var model: MyViewModel
var body: some View {
VStack {
Button(action: { self.model.counter += 1 },
label: { Text("Increment counter") })
Text("Counter value: \(model.counter)")
}
.frame(width: 480, height: 300)
}
init() { withUnsafePointer(to: self) { print("Initialising MyView struct instance \(String(format: "%p", $0))") }}
}
import Combine
class MyViewModel: ObservableObject {
private static var instanceCount: Int = 0 { didSet {
print("SettingsViewModel: \(instanceCount) instances")
}}
@Published
var counter: Int = 0 { didSet {
print("Model counter: \(counter), self: \(Unmanaged.passUnretained(self).toOpaque())")
}}
init() { print("Initialising MyViewModel class instance \(Unmanaged.passUnretained(self).toOpaque())"); Self.instanceCount += 1 }
deinit { print("Deinitialising MyViewModel class instance \(Unmanaged.passUnretained(self).toOpaque())"); Self.instanceCount -= 1 }
}
知道我做错了什么吗?
下图描绘了执行日志中的所有操作后应用的 UI。
【问题讨论】: