🍿
popover, sheetのisPresentedを子Viewにバインドせず(Environment Valuesを)使うとスッキリ書ける
概要
親のViewで childViewIsPresented
でpopoverで表示する子View ChildView
の表示非表示を切り替えているとする。(下のコード参照)
そのときEnvironment Valuesを使うことで、ChildView
にchildViewIsPresented
をバインドしなくても、ChildViewからchildViewIsPreseted
が読み取れ、またChildViewのdismissが可能である。
Environment Valuesとは、システム定義のEnvironmentObjectのようなものだと思っておけば良いと思う。
使うやつ
isPresented | Apple Developer Documentation
dismiss | Apple Developer Documentation
サンプルコード
Before
ParentView
@State private var childViewIsPresented: Bool = false
var body: some View {
...
ToolbarItem(...) {
Button("子Viewを開く") {
childViewIsPresented = true
}
.popover(isPresented: $childViewIsPresented, attachmentAnchor: .point(.top), arrowEdge: .top) {
ChildView(childViewIsPresented: $childViewIsPresented)
}
}
...
}
ChildView
childViewIsPresentedにtrue, falseを代入することで、ChildViewを含むpopoverの表示非表示を切り替える。
struct ChildView: View {
@Binding var childViewIsPresented: Bool
...
}
After
ParentView
ChildViewにchildViewIsPresentedをバインドしなくてよい。
var body: some View {
...
ToolbarItem(...) {
Button(...)
.popover(isPresented: $childViewIsPresented, attachmentAnchor: .point(.top), arrowEdge: .top) {
ChildView()
}
}
}
...
ChildView
このようにpopoverの引数に渡したisPresentedを使うことができる。
struct ChildView: View {
@Environment(\.isPresented) var childViewIsPresented: Bool
...
}
また以下のコードでは、dismiss.callAsFunction()
でpopoverを閉じることができる。
struct ChildView: View {
@Environment(\.isPresented) var childViewIsPresented: Bool
@Environment(\.dismiss) var dismiss: DismissAction
...
}
Discussion