How do I resume a published timer in SwiftUI after navigating to a different page?

主宰稳场 提交于 2020-08-20 11:26:45

问题


In the following Playground example, the UI updates with the current date correctly, however when navigating away from the page and coming back the timer does not resume ticking:

  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())

How do I have the timer start updating again when the page starts showing?

I have seen solutions that involve wrapping the Timer in another class, but nothing that can be done in the View.

I thought calling in connect() in onAppear {} would do it.


回答1:


Reinitializing your timer and date inside the onAppear would work:

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")
            }
        }
    }
}



回答2:


Timer is canceled when there is no more subscribers, and when timer is cancelled it cannot be started again... so you need to make either not cancelling timer or recreate timer every time first tab is selected.

Here is possible solution (case 1, tested with 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 !!
    }
}


来源:https://stackoverflow.com/questions/60888539/how-do-i-resume-a-published-timer-in-swiftui-after-navigating-to-a-different-pag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!