Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.1k views
in Technique[技术] by (71.8m points)

swiftui - NavigationLink doesn't fire after FullScreenCover is dismissed

I have a button in a view (inside a NavigationView) that opens a full screen cover - a loading screen while some data is processing. When the cover is dismissed, I want to automatically route to the next view programmatically. I'm using a NavigationLink with a tag and selection binding, and the binding value updates when the cover is dismissed, but the routing doesn't happen unless I tap that same "open modal" button again.

import SwiftUI

struct OpenerView: View {
    @EnvironmentObject var viewModel: OpenerViewModel
    
    @State private var selection: Int? = nil
    @State private var presentLoadingScreen = false
    
    var body: some View {
        VStack {
            NavigationLink(destination: SecondScreen(), tag: 1, selection: $selection) { EmptyView() }
            Button(action: {
                viewModel.frequency = 0
                self.presentLoadingScreen.toggle()
            }, label: {
                Text("Open cover")
            }).buttonStyle(PlainButtonStyle())
        }
        .navigationBarTitle("Nav title", displayMode: .inline)
        .fullScreenCover(isPresented: $presentLoadingScreen, onDismiss: {
            self.selection = 1
        }, content: ModalView.init)
    }
}

struct ModalView: View {
    @Environment(.presentationMode) var presentationMode
    
    var body: some View {
        Text("Howdy")
          .onAppear {
              DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                presentationMode.wrappedValue.dismiss()
              }
          }
    }
}

The first time I hit the Button, the cover opens. Inside the cover is just a DispatchQueue.main.asyncAfter which dismisses it after 2 seconds. When it's dismissed, the onDismiss fires, but then I have to hit the button again to route to SecondScreen.

Any ideas?

Edit: Added the modal's View question from:https://stackoverflow.com/questions/65860539/navigationlink-doesnt-fire-after-fullscreencover-is-dismissed

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I got it working with some changes to the code, and I'm sharing here along with what I think is happening.

I believe the problem is a race condition using a @State boolean to toggle the cover and the navigation. When the cover is being dismissed, my main OpenerView is being recreated - to be expected with state changes. Because of this, I try to set the @State var selection to trigger the navigation change, but before it can do so, the view is recreated with selection = nil.

There seem to be two ways to solve it in my case:

  1. Move the cover boolean to my view model - this worked, but I didn't want it there because it only applied to this view and it's a shared view model for this user flow. Plus, when the modal is dismissed, you see the current OpenerView for a brief flash and then get routed to the SecondScreen.
  2. Keep the cover boolean in @State, but trigger the navigation change in the button immediately after setting the boolean to open the modal. This worked better for my use case because the modal opens, and when it closes, the user is already on the next screen.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...