3

所以,我想要一个Text根据我的 CoreData 模型的内容来改变它的内容。为此,我在 Xcode beta 4 中使用了一个计算属性,但它似乎不再起作用了。这是一个错误还是我没有看到其他问题?

self.objectWillChange.send()我遇到的问题是我的视图(和计算的属性)在我的商店中调用时似乎没有得到更新。

我还尝试将我的 var '导出'到商店并从那里获取它,结果相同......


编辑: 我只是对另一个类进行了同样的尝试,但它并不能仅objectWillChange.send()用于但仅与@Published它一起工作,如果从 NSObject 继承的类即使停止工作...


我刚刚发现:与

struct Today: View {
    @EnvironmentObject var myStore: DateStore
    var hasPlans: Bool {
        guard let plans = myStore.getPlans() else { return false }
        return plans.isEmpty
    }

    var body: some View{
        VStack{
            Text(hasPlans ? "I have plans":"I have time today")
            Button(action: {
                self.myStore.addPlans(for: Date())
            }) {
                Text("I have plans")
            }
    }
}

class DateStore: NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
    private var fetchedResultsController: NSFetchedResultsController<DateStore>
    //...
    public func addPlans(for date: Date){
        //{...}
        if let day = self.dates.first(where: { $0.date == date}){
            day.plans += 1
            saveChanges()
        }else{
            self.create(date: dayDate)
        }
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        self.objectWillChange.send()
    }
}


这是我的问题的一个非常简化的版本,我知道我的 DataModel 工作是因为值发生了变化并被self.objectWillChange.send()调用,但我的视图由于某种原因没有更新......

4

3 回答 3

7

我不认为 N​​SObject 是问题的根源。问题似乎是你还没有实现objectWillChange. 编译器会让你侥幸逃脱,但结果是你objectWillChange什么都不做。

这是一个简单的示例,展示了如何使用绑定有效的计算属性配置 ObservableObject(即 NSObject):

class Thing : NSObject, ObservableObject {
    let objectWillChange = ObservableObjectPublisher()
    var computedProperty : Bool = true {
        willSet {
            self.objectWillChange.send()
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var thing : Thing
    var body: some View {
        VStack {
            Button(self.thing.computedProperty ? "Hello" : "Goodbye") {
                self.thing.computedProperty.toggle()
            }
            Toggle.init("", isOn: self.$thing.computedProperty).frame(width:0)
        }
    }
}

您可以通过点击按钮和开关来查看所有内容都是实时的并且响应视图中的绑定。

于 2019-08-01T01:31:50.580 回答
3

用我自己的代码试验表现出类似的问题。

当采用 ObservableObject 的 Class 是 NSObject 的子类时,@Publisher SwiftUI 的魔力似乎中断了。

简短的回答解决方案是,如果您可以在@Published 不是 NSObject 的子类时让它与它一起工作,那么当您使其成为 NSObject 的子类时,将 @Published 替换为

let objectWillChange = PassthroughSubject<Void, Never>()

您必须在 Class 文件中导入 Combine 框架才能执行此操作。

这是我正在试验的工作应用程序的一些代码。

风景:

import SwiftUI

struct ContentView: View {

    //Bind using @ObservedObject
    @ObservedObject var provider: Provider

    var body: some View {
        Text("\(self.provider.distance)")
    }
    ...
}

班上:

import Combine

class Provider: NSObject, ObservableObject {

    //Instead of using @Published, use objectwillchange
    //@Published var distance: CLLocationDistance = 0.0
    let objectWillChange = PassthroughSubject<Void, Never>()
    var distance = 0.0
    ...

    func calculateDistance() {
        ...
        // publish the change
        self.objectWillChange.send()
        self.distance = newDistance
    }
}
于 2019-08-01T00:14:58.610 回答
0

一种可行的解决方案是简单地制作一个 @State var的而不是使用计算的属性。然而,根据 WWDC 关于 SwiftUI 的讨论,这感觉有些不对,因为我的“实际状态”存在于我的数据模型中,并且通过声明一个新状态,@State我需要让它们保持同步,这违反了“单一事实来源”模式。是吗?

于 2019-07-31T12:36:54.603 回答