简体   繁体   中英

Timer crashing screens in SwiftUI

I have an app that is using a timer to scroll programmatically between views on the onboarding screen. From the onboarding screen, I can go to login then signup screen (or profile then my account screen). In both ways, when opening the login screen and clicking on signup, the signup screen appears but then disappears and takes me back to login (The same happens when I try to enter My Account screen from the profile screen). Check please the gif attached.

I've searched all around the web without finding any similar issue.

Note: I am using NavigationLink to navigate between screens, and I tried also to use both Timer, and Timer.TimerPublisher leading me to the same result, the screens will crash once the timer fires.

Note: When removing the timer (or the code inside onReceive) everything works fine. I also suspect that the issue could be related to menuIndex

struct OnboardingView: View {

//MARK: - PROPERTIES

@State var menuIndex = 0
@State var openLogin = false
let timer = Timer.publish(every: 4, on: .main, in: .common).autoconnect()

//MARK: - BODY

var body: some View {
    
    NavigationLink(destination: LoginView(), isActive: $openLogin) {}
    
    VStack (spacing: 22) {
        
        ProfileButton(openProfile: $openLogin)
            .frame(maxWidth: .infinity, alignment: .trailing)
            .padding(.horizontal, 22)
            
            OnboardingMenuItem(text: onboardingMenu[menuIndex].title, image: onboardingMenu[menuIndex].image)
                .frame(height: 80)
                .animation(.easeInOut, value: menuIndex)
                .onReceive(onboardingVM.timer) { input in
                    if menuIndex < onboardingMenu.count - 1 {
                        menuIndex = menuIndex + 1
                    } else {
                        menuIndex = 0
                    }
                }
            ...
        }
    }
}

You can only have one detail NavigationLink , if you want more you have to set isDetailLink(false) , this is why you are seeing the glitch.

FYI you're timer needs to be in @State or it will start from zero every time that View is init, eg on a state change of the parent View . The standard way to fix that is to group the related properties into their own struct, eg

struct OnboardingViewConfig {
    var menuIndex = 0
    var openLogin = false
    let timer = Timer.publish(every: 4, on: .main, in: .common).autoconnect()

    // mutating func exampleMethod(){} 
}

struct OnboardingView: View {

    @State var config = OnboardingViewConfig()

    ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM