首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI:观察已发布对象的内部更改

SwiftUI:观察已发布对象的内部更改
EN

Stack Overflow用户
提问于 2020-05-10 16:23:47
回答 2查看 6.2K关注 0票数 10

SwiftUI,SWIFT5.2,Xcode 11.4

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

代码语言:javascript
复制
final class Patient: ObservableObject {
      static var shared: Patient
      @Published var medicalData: MedicalData

      init { ... }

      final class MedicalData { 
            var allergies: String
            var ...

            init { ... }
      }
}

因此,在我的SwiftUI视图中:

代码语言:javascript
复制
struct ContentView: View {
       @ObservedObject var patient: Patient = Patient.shared
       var body: some view { ... }
}

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

代码语言:javascript
复制
patient.medicalData = NEW_MEDICAL_DATA --> OK! View refreshed

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

代码语言:javascript
复制
patient.medicalData.allergies = "Alcanfor" --> NOT PUBLISHED

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-24 14:46:53

找到了一种执行此操作的优雅方法(请参阅didSet):

代码语言:javascript
复制
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()’处初始化didSet属性之后编写medicalData代码。

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

票数 9
EN

Stack Overflow用户

发布于 2020-05-10 16:47:40

最简单的方法是使它成为值类型。

代码语言:javascript
复制
  struct MedicalData { 
        var allergies: String
        var ...

这给了我们

代码语言:javascript
复制
  patient.medicalData.allergies = "Alcanfor" --> PUBLISHED

更新:可能用于CoreData对象的方法。我仍然倾向于使用struct,现在用作包装器。它需要一些额外的努力,但允许控制哪些应该影响视图刷新而不应该刷新,并且通过现有的发布自动刷新自身。

代码语言:javascript
复制
// 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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61715183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档