はじめに
The Composable Archtecture (TCA) でsheet表示したViewを表示した側から閉じる方法について、とりあえず1パターンだけ示しておきます。
結論
- SwiftUIのおさらい
- SwiftUIではsheetとして表示したViewを閉じる方法としてEnvironmentValuesとしてPresentationModeがある
-
PresentationMode
はdismiss()
メソッドでViewを閉じれる- Viewのみに限定したロジックでViewを閉じたいときはこれだけでいい
-
- SwiftUIではsheetとして表示したViewを閉じる方法としてEnvironmentValuesとしてPresentationModeがある
- TCAでReducerの処理からViewを閉じたい場合どうするか
- Stateの変数が変わった場合、SwiftUIの
onChange(of:)
メソッドが検知できる-
onChange(of:)
メソッドのクロージャでPresentationMode
のdismiss()
を呼び出す
-
- Stateの変数が変わった場合、SwiftUIの
詳細
SwiftUIではsheetとして表示したViewを閉じる方法としてEnvironmentValuesとしてPresentationModeがある
サンプルコードとしてContentViewがChildViewをsheetで開き、ChildViewのPresentationMode
はdismiss()
メソッドで自身を閉じれる。
//: A UIKit based Playground for presenting user interface
import UIKit
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
@State var isPresented = false
var body: some View {
NavigationView {
Button(
action: {
print("action:", isPresented) // => false
isPresented = true
},
label: {
Text("Present View")
}
)
.sheet(isPresented: $isPresented) {
ChildView()
}
}
}
}
struct ChildView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
Button(
action: {
presentationMode.wrappedValue.dismiss()
},
label: {
Image(systemName: "xmark.square")
Text("Close")
}
)
}
}
PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())
Viewのみに限定したロジックでViewを閉じたいときはこれだけでいい。
コメントをもらったので気づけた話として、ContentViewのisPresented
はChildViewを閉じればfalseになってる。
これは$isPresented
として$
をつけることで@State
からvar projectedValue: Binding<Value> { get }
を取り出せているから。そのために.sheet(isPresented: $isPresented)
でseet
からfalseにできる。
TCAでReducerの処理からViewを閉じたい場合どうするか
StateのBoolを用意し、onChange(of:)
でviewStoreを見張ってその変化時にpresentationMode
を操作すればいい。
struct ChildSttate {
var isPresented = true
}
struct ChildView: View {
@Environment(\.presentationMode) var presentationMode
let store: Store<ChildState, ChildAction>
var body: some View {
WithViewStore(store) { viewStore in
Button(
action: {
presentationMode.wrappedValue.dismiss()
},
label: {
Image(systemName: "xmark.square")
Text("Close")
}
)
.onChange(of: viewStore.isPresented) { value in
if !value {
presentationMode.dismiss()
}
}
}
}
}
参考