Reputation: 539
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?
Upvotes: 18
Views: 4531
Reputation: 406
Seems to be a bug in the sheet
and fullScreenCover
modifiers. In my case it was calling its content
closure also after showing, hiding the keyboard and typing. To prevent the view from being recreated we can wrap it in a view adopting Equatable
which is always equal to its instances:
struct PersistentContentView<Content: View>: View, Equatable {
static func == (lhs: PersistentContentView<Content>, rhs: PersistentContentView<Content>) -> Bool {
true
}
let content: () -> Content
var body: some View {
content()
}
}
extension View {
func persistent() -> some View {
PersistentContentView { self }
}
}
.sheet(isPresented: $showingModal) {
Modal(showingModal: self.$showingModal)
.persistent()
}
Upvotes: 0
Reputation: 21
private let uniqueId: String = "uniqueId"
Button(action: {
self.showingModal.toggle()
}, label: {
Text("AAAA")
})
.sheet(isPresented: $showingModal) {
Modal(showingModal: self.$showingModal)
.id("some-unique-id")
}
Ex:
.id(self.uniqueId)
Add unique id to your .sheet and not't worry :)
But, do not use UUID(), because sheet view will be represented on every touch event
Upvotes: 1
Reputation: 3099
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.
Upvotes: 9
Reputation: 555
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.
Upvotes: 2
Reputation: 144
Comment out/remove the init() method from Modal with everything else the same. You should be able to solve the issue of two instances of Modal being created, its because you are explicitly initializing the binding (showingModal) in the init() of Modal. Hope this makes sense.
Upvotes: 0