🍎
[SwiftUI][TCA] Alert/Dialog
概要
この記事ではTCA初心者の筆者が理解を深めていくために、
pointfreeco
公式のサンプルアプリを基に理解しやすく整理していきます。
今回はAlertの使用例を整理して理解していきます。
今回扱うファイル
今回は公式サンプルの以下のファイルです。
AlertsAndConfirmationDialogs
表示するalertとconfirmationDialogでカウントが出来るようになっています。
State,Action
今回のAlertState
のConfirmationDialogState
は、
このライブラリに用意されており、
ボタンをタップしたときのアクションの送信を自動的に処理するので、
双方向バインディングやアクションクロージャーではなく、
リデューサーの中でその機能を適切に処理することができます。
またここでのポイントとしては、
AlertState
もConfirmationDialogState
も、
OptionalStateであることがポイントとなります。
struct AlertAndConfirmationDialogState: Equatable {
var alert: AlertState<AlertAndConfirmationDialogAction>?// OptionalState
var confirmationDialog: ConfirmationDialogState<AlertAndConfirmationDialogAction>?// OptionalState
var count = 0
}
enum AlertAndConfirmationDialogAction: Equatable {
case alertButtonTapped
case alertDismissed
case confirmationDialogButtonTapped
case confirmationDialogDismissed
case decrementButtonTapped
case incrementButtonTapped
}
Reducer
各Actionがコールされた際に、
alert
とconfirmationDialog
のState
の更新では、
.initで表示したい内容を設定出来ます。
まずはAlertStateから見ていきます。
AlertState
titleやmessage、Buttonなどの設定方法は以下のコードの通りです。
case .alertButtonTapped:
state.alert = .init(
title: .init("Alert!"),
message: .init("This is an alert"),
primaryButton: .cancel(.init("Cancel")),
secondaryButton: .default(.init("Increment"), action: .send(.incrementButtonTapped))
)
またAlertをから戻る際の挙動では、
alertDismissedというアクションを送ることで、
Alertが消えるようになります。
// View
.alert(
self.store.scope(state: \.alert),
dismiss: .alertDismissed
)
// Reducer
case .alertDismissed:
state.alert = nil
return .none
続いてConfirmationDialogStateを見ていきます。
ConfirmationDialogState
titleやmessage、Buttonなどの設定方法は以下のコードの通りです。
case .confirmationDialogButtonTapped:
state.confirmationDialog = .init(
title: .init("Confirmation dialog"),
message: .init("This is a confirmation dialog."),
buttons: [
.cancel(.init("Cancel")),
.default(.init("Increment"), action: .send(.incrementButtonTapped)),
.default(.init("Decrement"), action: .send(.decrementButtonTapped)),
]
)
return .none
Dialogから戻る際の挙動では、
confirmationDialogDismissedアクションを送り、
Dialogが消えるようになります。
基本的にはAlertと同じような処理となります。
// View
.confirmationDialog(
self.store.scope(state: \.confirmationDialog),
dismiss: .confirmationDialogDismissed
)
// Reducer
case .confirmationDialogDismissed:
state.confirmationDialog = nil
return .none
View,Store
struct AlertAndConfirmationDialogView: View {
let store: Store<AlertAndConfirmationDialogState, AlertAndConfirmationDialogAction>
var body: some View {
WithViewStore(self.store) { viewStore in
Form {
Section(header: Text(template: readMe, .caption)) {
Text("Count: \(viewStore.count)")
Button("Alert") { viewStore.send(.alertButtonTapped) }
Button("Confirmation Dialog") { viewStore.send(.confirmationDialogButtonTapped) }
}
}
}
.navigationBarTitle("Alerts & Confirmation Dialogs")
.alert(
self.store.scope(state: \.alert),
dismiss: .alertDismissed
)
.confirmationDialog(
self.store.scope(state: \.confirmationDialog),
dismiss: .confirmationDialogDismissed
)
}
}
Discussion