1

we have several SwiftUI screens that are presented as sheet. all of then can be dismissed by clicking a button.

so basically all of them have these 2 in common:

@Environment(\.presentationMode) var presentationMode
func dismiss() {
    presentationMode.wrappedValue.dismiss()
}

how can i declare them only once and just reuse them only in specific views? i cannot use inheritance since they are stucts, extensions cannot contain state (except using a holder struct) and would add these to all instances of the same view type.

1 Answer 1

3

The .presentationMode is available throughout current view hierarchy, so we can use this feature to wrap & manage dismiss in some modifier.

Here is a demo of solution based on button style, so any button can be specified as dismissing and it will dismiss current presentation.

Prepared with Xcode 12.1 / iOS 14.1

enter image description here

struct TestReuseDismissed: View {
    @State private var isActive = false
    var body: some View {
        Button("Show Sheet") {
            isActive = true
        }
        .sheet(isPresented: $isActive) {
            Button("Dismiss", action: { 
                   // do something before dismiss here !!
                })
                .buttonStyle(DismissButtonStyle())
        }
    }
}

struct DismissButtonStyle: PrimitiveButtonStyle {
    @Environment(\.presentationMode) var presentationMode

    func makeBody(configuration: Configuration) -> some View {
        Button(action: {
            configuration.trigger()
            dismiss()
        }) { configuration.label }
    }

    func dismiss() {
        presentationMode.wrappedValue.dismiss()
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

i have changed the first struct like this struct TestReuseDismissed: View { @State private var isActive = false var body: some View { Button("Dismiss", action: { // do something before dismiss here !! }) .buttonStyle(DismissButtonStyle()) } } and used it in a navigation bar: .navigationBarItems( leading: TestReuseDismissed() ). it should basically dismiss itself, the dismiss function is called but nothing happens
It is known - navigation bar is in different view hierarchy, it behaves the same if use custom view with presentation as navigation bar item, but if you use button in navigation link destination all works.
how did you know that it is in a different hierarchy? where can that kind of documentation be found?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.