WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Advanced Dismissing Views

Forums > Swift

I've referenced this tutorial for using a button action to dismiss sheets https://www.hackingwithswift.com/quick-start/swiftui/how-to-make-a-view-dismiss-itself

but I'm having trouble extending the idea to my usecase below:

I return a success from the server and switch the published property passwordChangeSuccessDismissSheet to true.

    @Published var passwordChangeSuccessDismissSheet = false

    @Published var passwordChangeFailedAfter = false

    func changeSlpUserPassword() {
        guard !isSending else {
            return
        }
        isSending = true
        let slpChangePassword = UserSLPChangePasswordRequest(old_Password: oldPassword, new_Password: newPassword)
        UserAccountWebService().changeSlpUserPassword(userSlpPass: slpChangePassword) { result in
            switch result {
            case .success():
                print("passwordChanged")
                DispatchQueue.main.async {
                    self.passwordChangeSuccessDismissSheet = true
                }
            case .failure(let error):
                print(error)
                DispatchQueue.main.async {
                    self.isSending = false
                    self.passwordChangeFailedAfter = true
                }
            }
        }
    }

As far as the view goes, I have the parent view with a button to bring up the sheet using the typical binding and modifier:

                    Button(action: { passwordChangeTapped = true }, label: {
                        Text("Change password")
                            .font(.custom("Poppins", size: 22))
                            .fontWeight(.regular)
                            .foregroundColor(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)))
                    })

Inside of the sheet, I only use a navigation bar item for a "Cancel" button which will dismiss the sheet:

            .navigationBarItems(trailing: Button(action: {
                showSheetPresented.toggle()
            }, label: {
                Text("Cancel")
            }))

The goal is for the sheet view to be listening for the change in my @Published property so that it will dismiss once the server returns the successful response.

Nothing seems to be working.

Any help would be great!

   

You have not shown how you have defined the class that has the @Published parameters, so I have taken Paul's example code and modified it to be for a class instead. Hopefully this will give you some ideas of how to change your code.

class DisplayThis: ObservableObject {
    @Published var displayIt = false
}

struct DismissingView1: View {
    @Environment(\.presentationMode) var presentationMode
    @StateObject var displayThis: DisplayThis

    private func changeDisplay() {
        if !displayThis.displayIt {
            presentationMode.wrappedValue.dismiss()
        }
    }

    var body: some View {
        Button("Dismiss Me") {
            displayThis.displayIt = false
        }
    }
}

struct ContentView: View {
    @StateObject var displayThis: DisplayThis

    var body: some View {
        Button("Show Detail") {
            displayThis.displayIt = true
        }
        .sheet(isPresented: $displayThis.displayIt) {
            DismissingView1(displayThis: displayThis)
        }
    }
}

If you did use this idea in the simplest program where there is just a ContentView, you would need to change the app swift file to prevent a compliation error.

from

ContentView()

to

ContentView(displayThis: .init())

   

Hi @Greenamberred I'm not sure I understand what you mean about the class with the @Published parameter. The only class involved is my View Controller with the @Published var passwordChangeSuccessDismissSheet = false block.

I've given this a shot and still am not finding the right results. If I understand, your private function which runs the presentationMode.wrappedValue.dismiss() should be in my view somewhere and be listening to the @Published property that lives in my View Controller, as stated above.

Let me know if I can share some more context or code on this because maybe my navigation and Sheet hirearchy is causing some of the problems?

Thanks for the help!

   

Yes, seeing the code for the view would be useful to try help you more specifically.

Somewhere you should be using the equivalent of

@Environment(\.presentationMode) var presentationMode
…
presentationMode.wrappedValue.dismiss()

or

.sheet(isPresented: $displayThis.displayIt) {  …

but using your parameters

passwordChangeSuccessDismissSheet and showSheetPresented.

   

I'll just drop the entire view for you. This is a user account view, with a sheet to change their password. As I mentioned, the goal here is to dismiss the "change password sheet" once the @Published property switches to True from my class.

I think ultimately what doesn't make sense is how I "listen" to the @Published property while at the same time bind to the local @State properties in my view that manage the sheet as well.

Ignore all the Account Image stuff.

struct SLPAccountProfileView: View {

    let slpAccountProfilePicVM = SLPAccountProfilePicture()

    @StateObject var slpAccountVM = SLPChangeAccountPassword()

    private let userAccountProperties = SLPDataManager.shared.returnUsersProfileDetails()

    @State private var passwordChangeTapped = false

    @State var selectedImage: UIImage?

    @State var profileImage: Image?

    @State var imagePickerPresented = false

    var body: some View {
        NavigationView {
            VStack {
                if profileImage == nil {
                    Button(action: { imagePickerPresented = true }, label: {
                        Image("ProfilePlaceholder")
                            .clipShape(Circle())
                            .frame(width: 72, height: 72)
                    })

                        .sheet(isPresented: $imagePickerPresented, onDismiss: loadImageFirstTime, content: {
                            ImagePicker(image: $selectedImage)

                        })
                } else if let image = profileImage {
                    VStack {
                        Button(action: { imagePickerPresented = true }, label: {
                            image
                                .resizable()
                                .scaledToFill()
                                .clipped()
                                .clipShape(Circle())
                                .frame(width: 72, height: 72)
                        })

                            .sheet(isPresented: $imagePickerPresented, onDismiss: loadNewImage, content: {
                                ImagePicker(image: $selectedImage)
                            })
                    }
                }
                VStack {
                    List {
                        Section(header: Text("Name")){

                            SLPAccountListItems(item: "\(userAccountProperties?.first_name ?? "empty")" + " \(userAccountProperties?.last_name ?? "empty")")
                        }
                        .font(.custom("Poppins", size: 12))
                        .foregroundColor(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)))

                        Section(header: Text("Email")){

                            SLPAccountListItems(item: userAccountProperties?.email ?? "empty")

                        }
                        .font(.custom("Poppins", size: 12))
                        .foregroundColor(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)))

                        Section(header: Text("Phone Number")) {

                            SLPAccountListItems(item: userAccountProperties?.mobile_number ?? "empty")

                        }
                        .font(.custom("Poppins", size: 12))
                        .foregroundColor(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)))

                        Section(header: Text("Timezone")) {

                            SLPAccountListItems(item: userAccountProperties?.timezone ?? "empty")

                        }
                        .font(.custom("Poppins", size: 12))
                        .foregroundColor(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)))
                    }
                    .listStyle(GroupedListStyle())

                    Button(action: { SLPDataManager.shared.logOut() }, label: {
                        Text("Log Out")
                            .font(.custom("Poppins", size: 18))
                            .fontWeight(.medium)
                            .foregroundColor(Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
                            .frame(width: 200, height: 50)
                            .background(Color(#colorLiteral(red: 0.1521442533, green: 0.4429811835, blue: 0.6690705419, alpha: 1)))
                            .cornerRadius(10)
                            .overlay(
                                RoundedRectangle(cornerRadius: 8)
                                    .stroke(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)), lineWidth: 1.3)
                            )

                    })
                        .padding(2)
                    Button(action: { passwordChangeTapped = true }, label: {
                        Text("Change password")
                            .font(.custom("Poppins", size: 22))
                            .fontWeight(.regular)
                            .foregroundColor(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)))
                    })
                        .padding(.bottom, 60)
                        .padding(.top, 10)
                }
            }
            .navigationViewStyle(StackNavigationViewStyle())
            .navigationBarHidden(true)
            .sheet(isPresented: $passwordChangeTapped, content: {
                PasswordChangeView(showSheetPresented: $passwordChangeTapped)
            })
        }
    }
}

struct PasswordChangeView: View {

    @StateObject var slpAccountVM = SLPChangeAccountPassword()

    @Binding var showSheetPresented: Bool

    var body: some View {

        NavigationView {
            VStack {
                Text("Change password")
                    .headline1TextStyle()
                    .padding(.bottom, 20)

                VStack {
                    HStack {
                        Image(systemName: "number")
                            .font(.system(size: 27, weight: .ultraLight))
                            .foregroundColor(slpAccountVM.isOldPasswordValid() ? .green : .black)

                        SecureField("Current password", text: $slpAccountVM.oldPassword)
                            .modifier(TextFieldStyle())
                    }
                    .padding(.bottom, 10)

                    HStack {
                        Image(systemName: "number")
                            .font(.system(size: 27, weight: .ultraLight))
                            .foregroundColor(slpAccountVM.isNewPasswordValid() ? .green : .black)

                        SecureField("New password", text: $slpAccountVM.newPassword)
                            .modifier(TextFieldStyle())
                    }
                    .padding(.bottom, 10)

//                    Text("You will be logged out after changing your password")
//                        .font(.custom("Poppins", size: 14))
//                        .fontWeight(.medium)
//                        .foregroundColor(.gray)
//                        .frame(maxWidth: 300, alignment: .center)
                }
                Spacer()

                if slpAccountVM.passwordFormVerified {
                    Button(action: { slpAccountVM.changeSlpUserPassword() }, label: {

                        ActivityIndicator(isAnimating: slpAccountVM.isSending)

                        Text(slpAccountVM.isSending ? "Submitting..." : "Submit")
                            .font(.custom("Poppins", size: 18))
                            .fontWeight(.medium)
                            .foregroundColor(Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
                            .frame(width: 200, height: 50)
                            .background(Color(#colorLiteral(red: 0.1521442533, green: 0.4429811835, blue: 0.6690705419, alpha: 1)))
                            .cornerRadius(10)
                            .overlay(
                                RoundedRectangle(cornerRadius: 8)
                                    .stroke(Color(#colorLiteral(red: 0.9803921569, green: 0.6784313725, blue: 0.2823529412, alpha: 1)), lineWidth: 1.3)
                            )

                    })
                }
                if slpAccountVM.passwordChangeFailedAfter == true {
                    Text("Something went wrong while trying to change your password. Please contact support if you continue to experience problems")
                        .font(.custom("Poppins", size: 14))
                        .fontWeight(.medium)
                        .foregroundColor(.red)
                        .frame(maxWidth: 300, alignment: .center)
                }

            }
            .navigationBarItems(trailing: Button(action: {
                showSheetPresented.toggle()
            }, label: {
                Text("Cancel")
            }))
        }

    }

}

   

Hacking with Swift is sponsored by Emerge

SPONSORED Optimize your app’s startup time, binary size, and overall performance using Emerge’s advanced app optimization and monitoring tools. Reliably measure app size, speed up your app's startup time with Emerge's Launch Booster, and much more. Emerge is actively used by many of the top mobile development teams in the world.

Find out more

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

Reply to this topic…

You need to create an account or log in to reply.

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.