W poniższym przykładzie Playground interfejs użytkownika aktualizuje się poprawnie z bieżącą datą, jednak po opuszczeniu strony i powrocie licznik czasu nie wznawia odliczania:

  import SwiftUI
  import PlaygroundSupport

  struct MainTabView: View {
    let timer = Timer.publish(every: 1, on: .main, in: .common)

    @State var time = Date()

    var body: some View {
        TabView {
            VStack {
                Text("\(time)").onReceive(self.timer) { self.time = $0 }
            }
            .onAppear { _ = self.timer.connect() }
            .tabItem {
                Text("Page 1")
            }

            Text("Page 2").tabItem {
                Text("Page 2")
            }

            Text("Page 3").tabItem {
                Text("Page 3")
            }
        }
    }
}

PlaygroundPage.current.setLiveView(MainTabView())

Jak mogę przywrócić licznik czasu do aktualizacji, gdy strona zacznie się wyświetlać?

Widziałem rozwiązania, które obejmują zawijanie Timera w innej klasie, ale nic nie można zrobić w widoku.

Pomyślałem, że zadzwonienie connect() w onAppear {} wystarczy.

1
chustar 27 marzec 2020, 17:57

2 odpowiedzi

Najlepsza odpowiedź

Ponowna inicjalizacja timera i daty w onAppear zadziała:

struct ContentView: View {
    @State private var timer = Timer.publish(every: 1, on: .main, in: .common)
    @State var time = Date()

    var body: some View {
        TabView {
            VStack {
                Text("\(time)").onReceive(self.timer) { self.time = $0 }
            }
            .onAppear(perform: {
                self.time = Date()
                self.timer = Timer.publish(every: 1, on: .main, in: .common)
                _ = self.timer.connect()
            })
            .tabItem {
                Text("Page 1")
            }

            Text("Page 2").tabItem {
                Text("Page 2")
            }

            Text("Page 3").tabItem {
                Text("Page 3")
            }
        }
    }
}
3
KevinP 27 marzec 2020, 15:16

Timer jest anulowany, gdy nie ma już abonentów, a gdy timer jest anulowany, nie można go ponownie uruchomić ... więc musisz albo nie anulować timera, albo ponownie utworzyć timer za każdym razem, gdy zostanie wybrana pierwsza zakładka.

Oto możliwe rozwiązanie (przypadek 1, testowany z Xcode 11.4)

struct MainTabView: View {
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    @State var time = Date()

    var body: some View {
        TabView {
            VStack {
                Text("\(time)")
            }
                .tabItem {
                    Text("Page 1")
            }

            Text("Page 2").tabItem {
                Text("Page 2")
            }

            Text("Page 3").tabItem {
                Text("Page 3")
            }
        }.onReceive(self.timer) { self.time = $0 } // here !!
    }
}
2
Asperi 27 marzec 2020, 15:17