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

发布于 2025-01-10 07:04:44 字数 1755 浏览 0 评论 0原文

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

这是我的代码:

import SwiftUI

struct ContentView: View {

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

}

struct FirstView : View {

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

}

struct SecondView: View {

@Binding var seconds : Int

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

}

欢迎任何帮助! 多谢

I'm pretty new at SwiftUI.
I would like to make an app that navigates through different views in a Navigation View and running a timer in background presenting the time on each of the views.
The problem is when I navigate to a second level of navigation. When the timer is on, the app returns automatically to the previous navigation view.
Here's is a screenshot video of what I mean:
https://youtu.be/eXbK9jpluvk

Here is my code:

import SwiftUI

struct ContentView: View {

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

}

struct FirstView: View {

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

}

struct SecondView: View {

@Binding var seconds : Int

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

}

Any help will be welcome!!
Thanks a lot

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听风念你 2025-01-17 07:04:44

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

NavigationView can only push on one detail NavigationLink so to have more levels you need to set .isDetailLink(false) on the link. Alternatively, if you don't expect to run in landscape split view, you could set .navigationViewStyle(.stack) on the navigation.

久而酒知 2025-01-17 07:04:44

就我而言, .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()
        }
    }
}

In my case .isDetailLink(false) didn't solve the issue, but I found another solution. Want to post in case someone would look for a similar case.

I had a button with timer that leads to the multilevel navigation. To solve the issue I moved the timer updates from higher-vew level to the level of button itself.

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()
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文