SwiftUI 通过导航视图中的视图共享计时器

问题描述 投票:0回答:2

我对 SwiftUI 还很陌生。 我想制作一个应用程序,可以在导航视图中浏览不同的视图,并在后台运行计时器,在每个视图上显示时间。 问题是当我导航到第二级导航时。当计时器打开时,应用程序会自动返回到之前的导航视图。 这是我的意思的屏幕截图视频: https://youtu.be/eXbK9jpluvk

这是我的代码:

导入 SwiftUI

结构ContentView:视图{

@State var timer = Timer.publish(every: 1,  on: .main, in: .common).autoconnect()
@State var seconds : Int = 0
@State var paused : Bool = true

var body: some View {
    
    
    VStack {
        Text("\(seconds)")
        Button(action: {
            paused.toggle()
        }) {
            Image(systemName: paused ? "play.fill" : "stop.fill")
        }
        NavigationLink(destination: FirstView( timerSeconds: $seconds, timerPaused: $paused)) {
            Text("Navigate 1")
        }.padding()
    }
    .onReceive(self.timer) { currentTime in
        if !paused {
            seconds = seconds + 1
            print(currentTime)
        }
    }
    .navigationViewStyle(.stack)
    
}

}

结构 FirstView:视图 {

@Binding var timerSeconds : Int
@Binding var timerPaused : Bool

var body: some View {
    
        VStack {
            Text("First View")
            Text("\(timerSeconds)")
            Button(action: {
                timerPaused.toggle()
            }) {
                Image(systemName: timerPaused ? "play.fill" : "stop.fill")
            }
            NavigationLink(destination: SecondView(seconds: $timerSeconds)) {
                Text("Navigate 2")
            }
        }
    
}

}

结构 SecondView:视图 {

@Binding var seconds : Int

var body: some View {
    Text("\(seconds)")
}

}

欢迎任何帮助! 非常感谢

swiftui timer navigationview
2个回答
1
投票

NavigationView
只能推送一个细节
NavigationLink
,因此要获得更多级别,您需要在链接上设置
.isDetailLink(false)
。或者,如果您不希望在横向分割视图中运行,您可以在导航上设置
.navigationViewStyle(.stack)


0
投票

就我而言,

.isDetailLink(false)
没有解决问题,但我找到了另一个解决方案。想发帖以防有人寻找类似的案例。

我有一个带有计时器的按钮,可以进行多级导航。为了解决这个问题,我将计时器更新从较高的视图级别移至按钮本身的级别。

struct LinkSentView: View {
    
    
    @ObservedObject var viewModel: LinkSentViewModel
    
    init(viewModel: LinkSentViewModel) {
        self.viewModel = viewModel
    }
    
    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            NavigationLink(destination: nameDestination(), isActive: $viewModel.fakeTrigger) { EmptyView() }
                .isDetailLink(false)
        ResendTimerButtonView(viewModel: ResendTimerButtonViewModel(resendLinkAction: viewModel.resendLink))
    enter code here
    }

class ResendTimerButtonViewModel: ObservableObject {
    
    private static let timeLimit = 30
    @Published private var timer: Timer?
    @Published private var timeRemaining = ResendTimerButtonViewModel.timeLimit
    
    var resendButtonText: String {
        timeRemaining > 0 ? "\(timeRemaining)s \(LinkSentView.Constant.resendButtonTitle)" : "\(LinkSentView.Constant.resendButtonTitle)"
    }
    
    var resendLinkAction: () -> ()
    
    init(resendLinkAction: @escaping () -> ()) {
        self.resendLinkAction = resendLinkAction
    }
    
    func startTimer() {
        timer?.invalidate()
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {[weak self] tempTimer in
            guard let self = self else { return }
            if self.timeRemaining > 0 {
                self.timeRemaining -= 1
            } else {
                tempTimer.invalidate()
            }
        }
    }
    
    func resendLink() {

    }
}

struct ResendTimerButtonView: View {
    @ObservedObject var viewModel: ResendTimerButtonViewModel
    var body: some View {
        Button(title: viewModel.resendButtonText, action: {
            viewModel.resendLink()
        })
        .onAppear {
            viewModel.startTimer()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.