SwiftUI не обновляется при публикации вручную - PullRequest
0 голосов
/ 07 января 2020

У меня есть класс, «циферблат» с регулярными обновлениями; он должен отображать массив метрик, которые меняются со временем.

Поскольку я хотел бы, чтобы часы также отображались в виджете, я обнаружил, что должен был поместить класс в каркас (возможно, есть другой путь, но я слишком далеко по дороге сейчас). Похоже, это вызвало проблему с 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 и установить его в случайное значение для попытки ручного обновления sh через send() на didSet без везения.

Так как я могу заставить периодическую c перерисовку дисплея?

Ответы [ 2 ]

1 голос
/ 08 января 2020

Что такое 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)")
  }
}
0 голосов
/ 21 января 2020

Так что прошло какое-то время, но я наконец заработал. Проблема казалась двоякой.

В моей структуре был определен класс, управляющий файлом 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 был обновлен так, как я хотел. Я не знаю, является ли это ожидаемым поведением, возможно, кто-то может сказать, должен ли я подать радар ....

...