0
votes

I have a view A that contains a NavigationView. A pushes View B by activating a NavigationLink. B pushes View C by activating a NavigationLink. C pushes View D by tapping a NavigationLink. D then presents a View as a sheet. If i dismiss the sheet the current top view is B. For some reason presenting the sheet pops 2 screens.

Can someone explain this behaviour and how i can fix it? I'm guessing somehow the navigation link in view B (that pushed view C) get deActivated but I cant figure out why

From what i tested it seems when the sheet gets presented ViewB gets reinitialized which will reinit my vm and so deactivate the link. How to i stop the view from being reinitialized?

struct ViewA: View {
@SwiftUI.Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
@ObservedObject private var viewModel: ViewAVM

var body: some View {
    NavigationView {
        GeometryReader { fullView in
            ScrollView(.vertical, showsIndicators: false) {
                if !self.viewModel.loading {
                    VStack(alignment: .leading, spacing: 0) {
                        DetailsView(car: self.$viewModel.data)
                        Spacer(minLength: 20)
                        NavigationLink(destination: ViewB(rootActive: self.$viewModel.showB), isActive: self.$viewModel.showB) {
                            Button(action: {
                                self.viewModel.showB = true
                            }) {
                                SecondaryButtonView(enabled: true, title: "Go")
                            }
                        }.isDetailLink(false).padding([.leading, .trailing], 20)
                    }.frame(minHeight: fullView.size.height)
                }
            }
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarTitle("View A")
        .navigationBarItems(leading: Button(action: {
            self.presentationMode.wrappedValue.dismiss()
        }) {
            Image("LeftArrow").renderingMode(.original)
        })
        .onAppear {
            self.viewModel.update()
        }
    }
    .navigationBarTitle("")
    .navigationBarHidden(true)
}

}

struct ViewBUI: View {
@SwiftUI.Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
@ObservedObject private var viewModel: ViewBVM
private let rootActive: Binding<Bool>
var body: some View {
    GeometryReader { fullView in
        ScrollView(.vertical, showsIndicators: false) {
            VStack(alignment: .leading, spacing: 0) {
                Text("").font(.regularParagraph).padding(.top, 15).padding(.bottom, 10)
                CustomEntryView()
                Spacer(minLength: 20)
                NavigationLink(destination: ViewC(rootActive: self.rootActive), isActive: self.$viewModel.showC) {
                    Button(action: {
                        self.hideKeyboard()
                        self.viewModel.validate()
                    }) {
                        PrimaryButtonView(enabled: self.viewModel.valid, title: "Continue")
                    }.disabled(!self.viewModel.valid)
                }.isDetailLink(false).padding(.bottom, 16)
            }.padding([.leading, .trailing], 20).frame(minHeight: fullView.size.height)
        }
    }
    .navigationBarBackButtonHidden(true)
    .navigationBarTitle(viewModel.new ? "New" : "Old")
    .navigationBarItems(leading: Button(action: {
        self.viewModel.rootActive.wrappedValue = false
    }) {
        Image("LeftArrow").renderingMode(.original)
    })
}

}

struct ViewDUI: View {
@SwiftUI.Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
let isDriver: Bool
let car: Binding<Car?>
let rootActive: Binding<Bool>

var body: some View {
    GeometryReader { fullView in
        ScrollView(.vertical, showsIndicators: false) {
                VStack(alignment: .leading, spacing: 0) {
                    Text("").font(.regularParagraph).foregroundColor(Color.black).padding([.leading, .trailing], 20).padding(.top, 15)
                    CarDetailsView(car: self.car)
                    Spacer(minLength: 20)
                    if self.car.wrappedValue?.mot == true && self.car.wrappedValue?.taxed == true {
                        if self.isDriver {
                            Button(action: {
                                self.rootActive.wrappedValue = false
                            }) {
                                PrimaryButtonView(enabled: true, title: "Save")
                            }.padding(.bottom, 16).padding([.leading, .trailing], 20)
                        } else {
                            NavigationLink(destination: ViewE(rootActive: self.$viewModel.showB)) {
                                PrimaryButtonView(enabled: true, title: "Continue")
                            }.isDetailLink(false).padding(.bottom, 16).padding([.leading, .trailing], 20)
                        }
                    } else {
                        Button(action: {
                            self.presentationMode.wrappedValue.dismiss()
                        }) {
                            PrimaryButtonView(enabled: true, title: "")
                        }.padding(.bottom, 16).padding([.leading, .trailing], 20)
                    }
                }.frame(minHeight: fullView.size.height)
        }
    }
    .navigationBarBackButtonHidden(true)
    .navigationBarTitle("")
    .navigationBarItems(leading: Button(action: {
        self.presentationMode.wrappedValue.dismiss()
    }) {
        Image("LeftArrow").renderingMode(.original)
    })
}

}

struct ViewEUI: View {
@SwiftUI.Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
private let rootActive: Binding<Bool>
private let isDriver: Bool
@State private var showingScanner = false
@State private var scanHandler: LicenseScanHandler!
@State private var scanCompleted = false

var body: some View {
    VStack(alignment: .leading, spacing: 0) {
        Text("")
            .font(.regularParagraph)
            .padding(.top, 15)
            .padding([.leading, .trailing], 20)
        ZStack(alignment: .topLeading) {
            VStack(alignment: .leading, spacing: 0) {
                Image("sample")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .padding(20)
            }
            .overlay(RoundedRectangle(cornerRadius: 3).stroke(Color.azure, lineWidth: 1))
            .background(Color.white.edgesIgnoringSafeArea(.all))
            .padding(.top, 12)
            Text("")
            .font(.tinyParagraph)
            .foregroundColor(.azure)
            .frame(width: 80, height: 24)
            .background(Color.white.edgesIgnoringSafeArea(.all))
            .cornerRadius(8)
            .overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.azure, lineWidth: 1))
            .padding(.leading, 20)
        }
        .padding([.leading, .trailing], 40)
        .padding(.top, 16)
        Spacer(minLength: 20)
        Button(action: {
            self.showingScanner = true
        }) {
            PrimaryButtonView(enabled: true, title: "Scan")
        }.padding(.bottom, 16).padding([.leading, .trailing], 20)
        .sheet(isPresented: $showingScanner) {
            ScannerWrapper(handler: self.scanHandler)
        }
        NavigationLink(destination: InfoUI(), isActive: $scanCompleted) {
            Text("")
        }.isDetailLink(false)
    }
    .background(Color.offWhite.edgesIgnoringSafeArea(.all))
    .navigationBarBackButtonHidden(true)
    .navigationBarTitle("")
    .navigationBarItems(leading: Button(action: {
        self.presentationMode.wrappedValue.dismiss()
    }) {
        Image("LeftArrow").renderingMode(.original)
    })
    .onAppear {
        self.scanHandler = LicenseScanHandler(delegate: self)
    }
}

}

1
Would you show your code? - Asperi
@Asperi Added code sample - Busu

1 Answers

0
votes

Although it is not documented, I realised that presenting a .sheet() while the view itself is set to a "no detail view" via .isDetailLink(false) causes this issue.

I can see why, as if the view is not a detail view it cannot present a sheet, hence the sheet is actually presented by the first detail view and that is why it goes back to that view right after the sheet is presented.

Try removing .isDetailLink(false) and finding a different workaround if you really need it to be not a detail link.