Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it in SwiftUI, when presenting modal view with .sheet, init() is called twice

I am producing the situation on WatchOS with the following code

struct Modal : View {
    @Binding var showingModal : Bool
    
    init(showingModal : Binding<Bool>){
        self._showingModal = showingModal
        print("init modal")
    }
    
    var body: some View {
        Button(action: {
            self.showingModal.toggle()
        }, label: {
            Text("TTTT")
        })
    }
}

struct ContentView: View {
    @State var showingModal = false
    var body: some View {
        Button(action: {
            self.showingModal.toggle()
        }, label: {
            Text("AAAA")
        }).sheet(isPresented: $showingModal, content: {Modal(showingModal: self.$showingModal)})
    }
}

Every time I press the button in the master view to summon the modal with .sheet, Two instances of the modal view are created.

Could someone explain this phenomenon?

like image 210
Alvar Avatar asked Feb 20 '20 08:02

Alvar


People also ask

How do I present a view in modal SwiftUI?

Modal views in SwiftUI are presented using the sheet modifier on a view or control. The simplest way is to have @State property to indicate when it should be visible. To hide the modal view, we can use the environment parameter or pass a binding to the modal view object.

How do I present and dismiss a view in SwiftUI?

The first option is to tell the view to dismiss itself using its presentation mode environment key. Any view can read its presentation mode using @Environment(\. presentationMode) , and calling wrappedValue. dismiss() on that will cause the view to be dismissed.

How do I create a bottom sheet in SwiftUI?

There are two steps to use a bottom sheet in SwiftUI. Set up sheet presentation like usual. Specified supported detents ( PresentationDetent ) to sheet's content via presentationDetents modifier.

What is a modal in SwiftUI?

Apr 25, 2021 · 9 min read · modal swift swiftui · Modal views are views that are presented over the main application and prevent interaction with the views behind until the modal view is dismissed.


2 Answers

I tracked this down in my code to having the following line in my View:

@Environment(\.presentationMode) var presentation

I had been doing it due to https://stackoverflow.com/a/61311279/155186, but for some reason that problem seems to have disappeared for me so I guess I no longer need it.

I've filed Feedback FB7723767 with Apple about this.

like image 125
Jeremy Avatar answered Sep 20 '22 09:09

Jeremy


It is probably a bug, as of Xcode 11.4.1 (11E503a). Beware, that if for example initializing view models (or anything else for that matter) like so:

.sheet(isPresented: $isEditingModalPresented) {
    LEditView(vm: LEditViewModel(), isPresented: self.$isEditingModalPresented)
}

the VM will be initialized twice.

like image 36
Adrian Avatar answered Sep 19 '22 09:09

Adrian