Search code examples
iosswiftswiftuiios-navigationviewproperty-wrapper

In SwiftUI, the application freeze without any warning when slide back halfway but released before completion


The following code reproduced the error:

import SwiftUI

struct ContentView: View {
    @State private var number: Int = 5
    var body: some View {
        NavigationView() {
            VStack(spacing: 20) {
                NavigationLink(destination: SecondView(bottles: $number)) {
                    Text("Click me")
                }
            }
        }
    }
}

struct SecondView: View {
    @Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
    @State private var color: UIColor = .black
    @Binding var bottles: Int

    var body: some View {
        Text("I have \(bottles) in my bag")
            .foregroundColor(Color(color))
            .navigationBarTitle(Text("Water Bottle"))
            .navigationBarItems(trailing:
                Button("Click") {
                    self.someFunction()
                }
        )
    }

    func someFunction() {
        if self.color == UIColor.black {
            self.color = .red
        } else {
            self.color = .black
        }
    }
}

When sliding back from SecondView to ContentView but didn't complete the gesture, the app freezes. When deleting either @Environment or NavigationBarItem will fix this error.

For @Environment, it is needed for CoreData but used presentationMode for reproduction of error


Solution

  • adding ".navigationViewStyle(StackNavigationViewStyle())" to the NavigationView fix the problem for me. This is the code I use for testing this on real devices (iPhone, iPad) and various simulators. Using macos 10.15.5, Xcode 11.5 and 11.6 beta, target ios 13.5 and mac catalyst.

    I have not tested this on all devices, so let me know if you find a device where this does not work.

    import SwiftUI
    
    struct ContentView: View {
    @State private var number: Int = 5
    var body: some View {
        NavigationView() {
            VStack(spacing: 20) {
                NavigationLink(destination: SecondView(bottles: $number)) {
                    Text("Click me")
                }
            }
        }.navigationViewStyle(StackNavigationViewStyle())  //  <---
    }
    }
    
    struct SecondView: View {
    @Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
    @State private var color: UIColor = .black
    @Binding var bottles: Int
    
    var body: some View {
        Text("I have \(bottles) in my bag")
            .foregroundColor(Color(color))
            .navigationBarTitle(Text("Water Bottle"))
            .navigationBarItems(trailing:
                Button("Click") {
                    self.someFunction()
                }
        )
    }
    
    func someFunction() {
        if self.color == UIColor.black {
            self.color = .red
        } else {
            self.color = .black
        }
    }
    }