Search code examples
iosswiftxcodepopover

Close a popover


I have managed to show a popover in my app. It can be closed with a swipi down. Works great. However, it is adviced to also show a button to close the popover. I tried to add this to the code, with all the tips on pop-ons and pop-overs given on the site, but sofa I failed. Can someone help me out? Must be an easy command but for a starter in xcode/swift it ins't easy to find.

The code to show the popover and the code in the popover itself:

...

      //The popover code in the ContentView that starts the popover
      Button(action: {
              presentPopup = true
            }, label: {
            Image(systemName: "questionmark.square")
            .foregroundColor(Color.gray)
                   })
            .padding(.leading)
            .popover(isPresented: $presentPopup, arrowEdge: .bottom) {
            Toelichting()
            .font(.footnote)
            }



//The code in the popover view:
 var body: some View {
    
    VStack {
        
        HStack {
        
        Text("Introduction")
            .font(.title2)
            .fontWeight(.bold)
            .multilineTextAlignment(.leading)
            .padding([.top, .leading])
        
        //Spacer ()
        
        // This should be the button to return to the main screen that ins't working
        //   Button  (action: {
        //      self.dismiss(animated: true, completion: nil)
        //    }, label: {
        //    Image(systemName: "xmark.circle")
        //    .foregroundColor(Color.gray)
        //    })
        //        .padding([.top, .trailing])
        }
        
         Divider()
            .padding(.horizontal)
            .frame(height: 3.0)
            .foregroundColor(Color.gray)

...

What should be Button action? Thanks for your time and help!


Solution

  • Rather than dismissing the popover using dismiss(), you need to pass a Binding value between both views.

    In this way, the value of the Binding will either be true, triggered by the main view, or false, triggered inside the popover.

    Here's your code:

    struct TopView: View {
        @State private var presentPopup = true    // This controls the popover
        
        var body: some View {
            //The popover code in the ContentView that starts the popover
            Button {
                presentPopup = true
            } label: {
                Image(systemName: "questionmark.square")
                    .foregroundColor(Color.gray)
            }
            .padding(.leading)
            .popover(isPresented: $presentPopup, arrowEdge: .bottom) {
                
                // You need to pass the Binding to the popover
                Toelichting(presentMe: $presentPopup)
                    .font(.footnote)
            }
        }
    }
    
    struct Toelichting: View {
        
        @Binding var presentMe : Bool    // This is how you trigger the dismissal
        
        var body: some View {
            VStack {
                
                HStack {
                
                Text("Introduction")
                    .font(.title2)
                    .fontWeight(.bold)
                    .multilineTextAlignment(.leading)
                    .padding([.top, .leading])
                
                Spacer ()
                
                    // This should be the button to return to the main screen that NOW IT'S FINALLY working
                   Button  (action: {
                       
                       // Change the value of the Binding
                       presentMe.toggle()
                       
                    }, label: {
                    Image(systemName: "xmark.circle")
                    .foregroundColor(Color.gray)
                    })
                        .padding([.top, .trailing])
                }
                
                 Divider()
                    .padding(.horizontal)
                    .frame(height: 3.0)
                    .foregroundColor(Color.gray)
            }
        }
    }