TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: How to close modal view from detail link if the structures are in different files?

Forums > SwiftUI

  //  MARK: ModalView() View
  List {
      NavigationLink() {
          //  MARK: DetailView() View
          List {
              Text("") // tapping on the text calls the desired function, after which the entire modal view should be closed
          }
      }
  }

Adding a dismiss() at the end of the function triggers a back action, but doesn't close the modal view. Lists are in different files.

There is also a dismiss in the modal view, and it closes the view. It is necessary to send a request for a dismiss from one view to another. There must be some easy way, but I can't find it.

2      

Try to pass it via binding instead of using dismiss()

struct ContentView: View {
    @State private var presentingModalView = false

    var body: some View {
        VStack {
            Button("Show modal") {
                presentingModalView = true
            }
        }
        .sheet(isPresented: $presentingModalView) {
            ModalView(isShowing: $presentingModalView)
        }
    }
}

struct ModalView: View {
    // use binding in order to dismiss the view
    @Binding var isShowing: Bool

    var body: some View {
        Text("Modal View")
            .onTapGesture {
                // dismissing the modal view
                isShowing = false
            }
    }
}

UPD:

Using your logic this should look something like this.

struct ContentView: View {
    @State private var presentingModalView = false

    var body: some View {
        VStack {
            Button("Show modal") {
                presentingModalView = true
            }
        }
        .sheet(isPresented: $presentingModalView) {
            ModalView(isShowingModal: $presentingModalView)
        }
    }
}

struct ModalView: View {
    // use binding in order to dismiss the view
    @Binding var isShowingModal: Bool

    var body: some View {
        NavigationStack {
            List {
                NavigationLink("Detail View") {
                    List {
                       Text("Tap me to dismiss")
                            .onTapGesture {
                                // dismissing the modal view
                                isShowingModal = false
                            }
                    }
                }
            }
        }
    }
}

3      

Thank you @ygeras for the extended answer. I thought that I should use @Binding. But I have almost all the problems with the project related to misunderstanding the connection of the view files :)

And this solution causes a lot of errors in the code. Since the structure of the views does not consist of two, but four files.

ContentView() file > .sheet ModalView() file > ModalSectionView() file with NavigationLink to > DetailListView() file

Perhaps I should rethink the structure of my application and use only one file per view until I gain more knowledge and understanding...

2      

Probably better idea to change the structure, but once again depends on the goal you want to achieve. But basically you can pass @Binding var to deeper views you don't necessarily use them in all the views. Like so:

ContentView(@State var) file > .sheet ModalView(@Binding var) file > ModalSectionView(@Binding var) file with NavigationLink to > DetailListView(@Binding var) file <- and here you change it to false making it dismiss the ModalView

in all subviews you bind(refer to) it to state var, and then you change it to false making it do dismiss the Modal View

As an example you can have any number of views as you need. The issue in choosing this way, you have to pass binding all the way down. For example refering to ObservableObject and injecting one in environment you can use it without passing down but directly from the view in which it is required.

struct ContentView: View {
    @State private var presentingModalView = false
    var body: some View {
        VStack {
            Button("Show modal") {
                presentingModalView = true
            }
        }
        .sheet(isPresented: $presentingModalView) {
            ModalView(isShowingModal: $presentingModalView)
        }
    }
}

// Modal View file
struct ModalView: View {
    // passing the binding in order to dismiss the view
    @Binding var isShowingModal: Bool

    var body: some View {
       ModalSection(isShowingModal: $isShowingModal)
    }
}

// Modal Section View file
struct ModalSection: View {
    // passing the binding in order to dismiss the view
    @Binding var isShowingModal: Bool

    var body: some View {
        NavigationStack {
            List {
                NavigationLink("Detail View") {
                    List {
                       DetailView(isShowingModal: $isShowingModal)
                }
            }
        }
    }
}

// Detail View file
struct DetailView: View {
    // passing the binding in order to dismiss the view
    @Binding var isShowingModal: Bool

    var body: some View {
        Text("Tap me to dismiss")
            .onTapGesture {
                // HERE you dismiss the modal view
                isShowingModal = false
            }
        }
    }
}

3      

With injecting object in enviroment may look like this

// Create observable object
class DismissView: ObservableObject {
    @Published var isPresentingModalView = false
}

struct ContentView: View {
    // initialize object
    @StateObject var mv = DismissView()

    var body: some View {
        VStack {
            Button("Show modal") {
                mv.isPresentingModalView = true
            }
        }

        .sheet(isPresented: $mv.isPresentingModalView) {
            ModalView()
                // inject in root view to be available in subviews environment
                .environmentObject(mv)
        }
    }
}

// Modal View file
struct ModalView: View {

    var body: some View {
       ModalSection()
    }
}

// Modal Section View file
struct ModalSection: View {

    var body: some View {
        NavigationStack {
            List {
                NavigationLink("Detail View") {
                    List {
                       DetailView()
                }
            }
        }
    }
}

// Detail View file
struct DetailView: View {
    // you refer to object that have value for dismissing the modal view
    @EnvironmentObject var mv: DismissView

    var body: some View {
        Text("Tap me to dismiss")
            .onTapGesture {
                // HERE you dismiss the modal view
                mv.isPresentingModalView = false
            }
        }
    }
}

// This is for preview purposes you have to add environment object as well
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(DismissView())
    }
}

3      

Thanks to @ygeras for the expanded code example, I will try .

2      

Hacking with Swift is sponsored by String Catalog.

SPONSORED Get accurate app localizations in minutes using AI. Choose your languages & receive translations for 40+ markets!

Localize My App

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.