【问题标题】:SwiftUI not being updated with manual publishSwiftUI 未通过手动发布进行更新
【发布时间】:2020-01-07 20:19:47
【问题描述】:

我有一个班级,一个定期更新的“钟面”;它应该显示一系列随时间变化的指标。

因为我希望时钟也显示在小部件中,所以我发现我必须将类放入框架中(也许还有另一种方法,但我现在走得太远了)。这似乎导致 SwiftUI 和可观察对象出现问题。

在我的View 我有:

@ObservedObject var clockFace: myClock

在钟面上我有:

class myClock: ObservableObject, Identifiable {
    var id: Int 
    @Publish public var metric:[metricObject] = []
    ....
    // at some point the array is mutated and the display updates
}

我不知道是否需要Identifiable,但这对结果没有任何影响。 public 是编译器要求的,但一直都是这样。

通过这些行,我在应用启动时收到运行时错误:

objc[31175] 元类没有类

于是我把@Published去掉,改为手动更新:

public var metric:[metricObject] = [] {
    didSet {    
        self.objectWillChange.send()`
     }
}

现在我得到一个显示,通过设置断点我可以看到send() 正在定期调用。但是除非我从数组中添加/删除,否则显示不会更新。我猜计算变量(构成 metricObject 更改的大部分,SwiftUI 没有看到。我随后尝试将“虚拟”Int 添加到 myClock 类并将其设置为尝试通过 send() 在其 didSet 上触发手动刷新的随机值。

那么如何强制定期重绘显示?

【问题讨论】:

    标签: swift swiftui observableobject observedobject


    【解决方案1】:

    什么是 MetricObject,您能否将其设为 struct,以便免费获得 Equatable

    当我使用 Int 执行此操作时,它可以工作:

    class PeriodicUpdater: ObservableObject {
      @Published var time = 0
      var subscriptions = Set<AnyCancellable>()
      init() {
        Timer
          .publish(every: 1, on: .main, in: .default)
          .autoconnect()
          .sink(receiveValue: { _ in
            self.time = self.time + 1
          })
          .store(in: &subscriptions)
      }
    }
    
    struct ContentView: View {
      @ObservedObject var updater = PeriodicUpdater()
      var body: some View {
        Text("\(self.updater.time)")
      }
    }
    

    【讨论】:

    • 谢谢,我会仔细看看你的代码。希望这只是使用 yourTimer 设置的简单案例。 metricObject 是一个标准 (?) 类 - 没什么太复杂的。我可以将其设为struct,只是将其全部置于框架中的行为导致了问题。不过我也可以试试。
    • 我无法使用此代码:@Published 会导致问题中所述的崩溃。
    【解决方案2】:

    所以花了一段时间,但我终于让它工作了。问题似乎有两个方面。

    我在我的框架中定义了一个控制 SwiftUI 文件的类。此类在主应用程序和小部件中都是子类。

    首先我不能在框架内的主类中使用@Published。这似乎导致了错误:

    objc[31175] 元类没有类

    所以我使用了@JoshHomman 的 iVar 想法,该想法会定期更新,但这对我来说并不适用。使用我的 SwiftUI 文件,我有:

    struct FRMWRKShape: Shape {
      func drawShape(in rect: CGRect) -> Path {
        // draw and return a shape
      }
    }
    
    struct ContentView: View {
      @ObservedObject var updater = PeriodicUpdater()
      var body: some View {
        FRMWRKShape()
        //....
        FRMWRKShape() //slightly different parameters are passed in
      }
    }
    

    ContentView 按我的意愿每秒执行一次,但是 FRMWRKShape 代码被调用但未执行(?!) - 除了第一次启动 - 所以视图不会更新。当我改用远不如 D.R.Y. 的东西时。如:

    struct ContentView: View {
     @ObservedObject var updater = PeriodicUpdater()
     var body: some View {
      Path { path in
              // same code as was in FRMWRKShape()
      }
            //....
      Path { path in
         // same code as was in FRMWRKShape()
         // but slightly different parameters
      }
     }
    }
    

    神奇的是,View 已按照我的意愿进行了更新。我不知道这是否是预期的行为,也许有人可以说我是否应该提交雷达....

    【讨论】:

      猜你喜欢
      • 2023-04-08
      • 2020-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-26
      • 1970-01-01
      • 2019-05-29
      相关资源
      最近更新 更多