最近在學習 SwiftUI ,寫了一個計算器的 Demo。寫完後學習並理解到一種代碼設計,感受頗有收穫,在此記錄一下。git
咱們將 App 看成一個狀態機,狀態機的狀態決定 App 的界面。首先咱們理出 App 都有什麼狀態?每一個狀態須要什麼樣的條件會觸發什麼樣的 Action?Action 執行後狀態機會進入什麼樣的次態?理清這些後,根據設計,隨着狀態機狀態的改變,,App 的界面天然會跟着更新。github
在這裏我用我寫的計算器 Demo 爲例講解下這種方式。swift
計算器的業務邏輯就是接受用戶的輸入的算式,而後計算並輸出算式的結果。那麼計算器的狀態就是由算式的狀態來決定。markdown
首先看看算式的組成:app
「左側數字 + 計算符號 + 右側數字 + 計算符號或者等號」oop
看着算式的結構,咱們就能捋出計算器都有什麼狀態:學習
因此咱們須要在代碼中定義出五個狀態:編碼
// 這五個枚舉和上面定義的狀態按順序一一對應 enum CalculatorState { case left(String) case leftOp(left: String, op: Calculator.Op) case leftOpRight(left: String, op: Calculator.Op, right: String) case equal(value: String) case error } 複製代碼
狀態咱們已經定義出來了,接下來就須要定義改變狀態時須要的 Action 了。spa
這裏主要以狀態 1(left)爲例,講解在狀態 1 下遇到什麼條件會觸發什麼樣的 Action,而後會進入哪一個狀態。設計
left
,只不過這個狀態下的數據會發生改變語言是蒼白的,直接看代碼:
// 因爲代碼過長,所有附上會影響篇幅,此處僅附上部分代碼。詳細代碼能夠在文末找到連接 func apply(item: CalculatorButtonItem) -> CalculatorState { switch item { case .digit(let num): return apply(num: num) case .dot: return applyDot() case .op(let op): return apply(op: op) case .command(let command): return apply(command: command) } } private func apply(num: Int) -> CalculatorBarin { switch self { case .left(let left): return .left(left.apply(num: num)) case .leftOp(let left, let op): return .leftOpRight(left: left, op: op, right: "0".apply(num: num)) case .leftOpRight(let left, let op, let right): return .leftOpRight(left: left, op: op, right: right.apply(num: num)) case .equal(_): return .left("0".apply(num: num)) case .error: return .left("0".apply(num: num)) } } 複製代碼
上面只解釋了狀態 1 進入次態須要的條件和進入次態前會作的 Action,其餘的狀態其實都是相似的,此處就再也不贅述。
計算器的業務比較簡單,用來闡述代碼設計會清晰易懂一些。這種代碼設計並非萬金油,哪裏都能用,不過確定也有不少比較適用的場景。好比應用商店的詳情頁面,詳情頁面的狀態就比較多,並且狀態和狀態之間的區別比較清晰,用這種方式來處理就比較合適。
固然這種設計也是有他的侷限所在。
好比當業務比較複雜的時候可能會由於發生狀態數量爆炸,此時代碼應該就會失控了。其餘的缺陷暫時尚未想到,等我進行一次最佳實踐後可能會發現更多的問題。
天底下不存在一個絕對正確的設計,都須要根據實際狀況本身作出相應的調整,以不變應萬變~
本文完整代碼地址:github.com/T-Oner/Swif…
我在學習 SwiftUI,如何你也對這個感興趣,那麼我推薦這本我在用的教材:
本文僅爲我的意見,不構成編碼建議。