1

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

因为我希望时钟也显示在小部件中,所以我发现我必须将类放入框架中(也许还有另一种方法,但我现在走得太远了)。这似乎导致了 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()它被定期调用。但是除非我从数组中添加/删除,否则显示不会更新。我在猜测计算变量(metricObjectSwiftUI 没有看到这些变化的大部分。我随后尝试向该类添加一个“虚拟”Int并将其myClock设置为随机值以尝试触发手动通过它刷新send()didSet没有运气。

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

4

2 回答 2

2

什么是 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)")
  }
}
于 2020-01-07T22:41:54.753 回答
0

所以花了一段时间,但我终于让它工作了。问题似乎是双重的。

我在我的框架中定义了一个控制 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代码被调用但没有执行(?!) - 除了第一次启动 - 所以视图不会更新。当我改用远不那么干燥的东西时,例如:

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是,它按照我想要的方式进行了更新。我不知道这是否是预期的行为,也许有人可以说我是否应该提交雷达....

于 2020-01-21T16:42:19.940 回答