SwiftUI:观察已发布对象的内部变化



SwiftUI, Swift 5.2, Xcode 11.4

我正在尝试观察单例中的更改,但我并不总是刷新我的 SwiftUI 视图:

final class Patient: ObservableObject {
static var shared: Patient
@Published var medicalData: MedicalData
init { ... }
final class MedicalData { 
var allergies: String
var ...
init { ... }
}
}

所以,在我的 SwiftUI 视图中:

struct ContentView: View {
@ObservedObject var patient: Patient = Patient.shared
var body: some view { ... }
}

如果有任何对象替换了医疗数据,发布者将正确通知我的 SwiftUI:

patient.medicalData = NEW_MEDICAL_DATA --> OK! View refreshed

但是,如果任何对象更改了当前医疗数据中的值,则不会刷新 SwiftUI 视图:

patient.medicalData.allergies = "Alcanfor" --> NOT PUBLISHED

有谁知道如何做到这一点? 提前谢谢你。

找到了一种优雅的方式来执行此操作(见didSet(:

final class Patient: ObservableObject {
static var shared: Patient
@Published var medicalData = MedicalData() { 
didSet {
subscription = medicalData.objectWillChange.sink { [weak self] _ in
self?.objectWillChange.send()
}
}
}
var subscription: AnyCancellable?
init { ... }
}

如果属性已初始化,则这开箱即用。如果没有,只需在初始化 'init((' 处的medicalData属性后编写didSet代码。

当然,MedicalData必须符合ObservableObject协议。

最简单的是使其成为值类型

struct MedicalData { 
var allergies: String
var ...

这给了

patient.medicalData.allergies = "Alcanfor" --> PUBLISHED

更新:核心数据对象的可能方法...我仍然更喜欢使用结构,现在作为包装器。它需要一些额外的努力,但允许控制什么应该影响视图刷新,不应该,刷新本身通过现有的发布自动工作

// helper struct wrapper
struct CoreDataWrapper<T:NSManagedObject> {
let value: T
init(_ wrapped: T) {
value = wrapped
}
private var refreshed = false
private mutating func refresh() {
refreshed.toggle()
}
}
// helper protocol of properties visible to extensions (optionals - works w/o it as well)
protocol MedicalDataProtocol {
var allergies: String? { get set }
}
// extension to wrapper for a specific class properties
extension CoreDataWrapper: MedicalDataProtocol where T == MedicalData {
var name: String? {
get { value.allergies }
set { value.allergies = newValue; refresh() }
}
}

// usage in view model
final class Patient: ObservableObject {
static var shared: Patient
@Published var medicalData: CoreDataWrapper<MedicalData>
// ... other code here

最新更新