問題
メニューの中にisPresentedを切り替えて、Text("Next View")をsheet表示させるボタンがあります。
以下のコードで動くでしょうか?
struct ContentView: View {
@State var isPresented = false
var body: some View {
Menu {
Button {
isPresented.toggle()
} label: {
Text("Button")
}
.sheet(isPresented: $isPresented) {
Text("Next View")
}
} label: {
Text("Menu")
}
}
}
解答: なんと動きません!
動かない原因は、.sheet
(View Modifier)の位置です。
Menu内のButtonはクリックされた瞬間に消えてしまいます。
そのため.sheet
(View Modifier)も消えてしまうのです。
解決方法(Tips)
Buttonでsheet表示させたい時はButtonの一段階上にさせよう
struct ContentView: View {
@State var isPresented = false
var body: some View {
Menu {
Button {
isPresented.toggle()
} label: {
Text("Button")
}
} label: {
Text("Menu")
}
.sheet(isPresented: $isPresented) {
Text("Next View")
}
}
}
alertやfullScreenCoverも同様
struct ContentView: View {
@State var isPresented = false
var body: some View {
Menu {
Button {
isPresented.toggle()
} label: {
Text("Button")
}
.alert("Alert", isPresented: $isPresented) {
Button("Close") {}
}
} label: {
Text("Menu")
}
}
}
おまけ(PhotosPicker)
このコードも一見動きそうですが、動きません。
import PhotosUI
struct ContentView: View {
@State var photoItem: PhotosPickerItem?
var body: some View {
Menu {
PhotosPicker("Photo", selection: $photoItem)
} label: {
Text("Menu")
}
}
}
これは動きます。
struct ContentView: View {
@State var isPresented = false
@State var photoItem: PhotosPickerItem?
var body: some View {
Menu {
Button("Photo") { isPresented.toggle() }
} label: {
Text("Menu")
}
.photosPicker(isPresented: $isPresented, selection: $photoItem)
}
}
これからわかるPhotosPickerの実装
こういった実装のためMenu内では動作しないことがわかる
struct PhotosPicker: View {
@State var isPresented: Bool = false
@Binding var photoItem: PhotosPickerItem?
var body: some View {
Button("Photo") {
isPresented.toggle()
}
.photosPicker(isPresented: $isPresented, selection: $photoItem)
}
}