0

I have a weird issue, where I navigate to EditView and edit a state variable from ContentView. After that I dismiss EditView with presentation.wrappedValue.dismiss(). The problem is, as soon as the view is dismissed, it reappears again.

I'm using XCode 12.4 and my iOS deployment target is set to 14.4

Observations:

  • EditView doesn't reappear if the value isn't edited
  • removing the changed value Text("Value: \(title)") >> Text("Value") from ContentView tree resolves the issue, but that obviously isn't a solution.
  • moving the NavigationLink from .toolbar e.g.
    VStack {
        Text("Value: \(title)")
        NavigationLink(destination: EditView(title: $title)){
            Text("Edit")
        }
    }

also resolves the issue, but that seems like a hack. Besides, I'd like to keep using .toolbar because I like the .navigationTitle animation and I can't have a button in the upper-right corner of the screen if I have a navigation title without the toolbar.

Here's the full code:

    import SwiftUI

    struct ContentView: View {
        @State var title: String = "Title"
        @State var isActive: Bool = false
        
        var body: some View {
            NavigationView {
                    
                Text("Value: \(title)")
                    .toolbar {
                        ToolbarItem(placement: .navigationBarTrailing) {
                            NavigationLink(destination: EditView(title: $title, isActive: $isActive), isActive: $isActive){
                                Text("Edit")
                            }
                        }
                    }
            }
        }
    }
    
    struct EditView: View {
        @Environment(\.presentationMode) var presentation
        
        @Binding var title: String
        @Binding var isActive: Bool
        
        var body: some View {
            Button(action: {
                title = "\(Date().timeIntervalSince1970)"
    //            presentation.wrappedValue.dismiss()
                isActive = false
            }){
                Text("Done")
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }

As far as I can tell this is a .toolbar bug, and if it turns out that way I'll report it to Apple, but in the meantime, does anyone have a better solution and/or explanation for this?

Cheers!

EDIT:

I updated the code with isActive value for the NavigationLink. It doesn't work when written like that, but uncommenting the commented out line makes it work. But that's quite hacky.

0

1 Answer 1

1

You are mixing up 2 things NavigationLink will push the view on stack, just like NavigationController in swift. That’s why you can see back button after navigating to second view. When you hit back button, it will pop top most view out of stack. presentationMode is not needed , dismissing presented view will not pop it of the stack.

To present a view and dismiss it you can check below code.

import SwiftUI

struct ContentViewsss: View {
    @State var title: String = "Title"
    @State var isPresented = false
    
    var body: some View {
        NavigationView {
            Text("Value: \(title)")
                .toolbar {
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button(action: {
                            isPresented.toggle()
                        }){
                            Text("Edit")
                        }
                    }
                }
        }.sheet(isPresented: $isPresented, content: {
            EditView(title: $title, state: $isPresented)
        })
    }
}

struct EditView: View {
   
    @Binding var title: String
    @Binding var state: Bool
    
    var body: some View {
        Button(action: {
            title = "\(Date().timeIntervalSince1970)"
            state.toggle()
        }){
            Text("Done")
        }
    }
}

If you want NavigationLink functionality, you can just remove presentationMode code from second view, and keep ContentView as it is -:

struct EditView: View {
     //@Environment(\.presentationMode) var presentation
    
    @Binding var title: String
      
    var body: some View {
        Button(action: {
            title = "\(Date().timeIntervalSince1970)"
            // presentation.wrappedValue.dismiss()
        }){
            Text("Done")
        }
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

the thing is, i need to dismiss the view programmatically - when I press the 'done' button, and afaik presentationMode is the only way?
@EliseyOzerov didn’t get you. If you don’t want to use presentationMode to dismiss, you can also pass isPresented state property as binding to EditView, and toggle it back to false on done button.
I just tried that, but nothing happens. The interesting part is that if I try both at the same time, it works. But that's a hacky solution lol
@EliseyOzerov can you update your code with what you tried.
i cant use sheet modifier there because the code in ContentView is already in a sheet in my project - I updated the code btw
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.