ReduxとSwiftUIについて
Redux
状態は複数のView, Controllerが相互に依存するので管理が難しい
そこで,相互にイベントを発火させるのをやめて,単一方向にのみ状態が流れるように
ユーザ操作で変数が変更→変更を検知したらレンダリング
さらに,変数変更とレンダリングの間に更新ロジックを挟むのがRedux
Reduxはグローバルな状態を管理するのが目的.コンポーネント内部で完結する変数はStoreで管理しないほうがbetter
更新するたびにレンダリングが走るのでパフォ落ちる
Q. これはグローバル変数と広義的には同義では?
A. ほぼ合ってる(要出典)
そもそもグローバル変数はなぜ嫌われるか
主な理由は「誰でもいつでもアクセスできるから」
あるロジックの動作中に別のロジックが変数を変えてしまうことで一貫性が崩れる.
ならば,関数を変数ドリブンにして,変数が変わったら常に"イベントが発火→同期"されれば良い.
「関数の発火点を変数の変更イベントにする⇔単一フロー」が肝
このフローをフレームワークに落とし込んだのがRedux
https://gyazo.com/b9df841bac84bc5fa0d727926b2b6bdc
https://gyazo.com/51f7ca7fc536808ae7a6329674bee30e
余談
Reduxを包含するフレームワークとしてRecoilがある
誤解を恐れずに一言でまとめれば、RecoilはReduxからreducerを消してフックに最適化したステート管理ライブラリです
Recoil : 状態はAtomで管理され(名前の通りatomは複数存在),Selectorが変更→Selectorが変更→...
SwiftUIとpure UIKitにおける状態管理の違い
SwiftUIはSingle Source of Truthを標榜
Single Source of Truth : 簡単に言えば変数のコピーを作らない.変数は同期されるべきという思想.
関数を変数ドリブンにして,変数が変わったら常に"イベントが発火→同期"されれば良い.
SwiftUIでは,Redux同様,この「同期処理」が全て内部で行われる.
ここがUIKitとの違いであり,SwiftUIでは同期処理を自前で書いてはならない.
自前での同期処理って具体的には何?
didSetによるview変更
自前で書いてしまうと,書き忘れが生じたりコーディング量が増大するため,好ましくない.
pureなUIKitの例
code:uikit.swift
class SampleViewController: UIViewController {
var labelState: Bool = false {
didSet { // 自前で書いた同期処理
label.text = "\(labelState)"
}
}
@IBOutlet weak var label: UILabel!
@IBAction func switchToggle(_ sender: UISwitch) {
self.labelState = sender.isOn
}
}
SwiftUIの例
code:sui.swift
struct SampleView: View {
@State private var labelState = false
var body: some View {
VStack {
Toggle(isOn: $labelState, label: {})
Text("\(labelState)").padding()
}
}
}
View間の状態管理は@Bindingを付けることで実現される.
SwiftUIの状態管理は小さいReduxのような感じ