---
# System prepended metadata

title: 善用狀態機架構　大幅簡化 View Controller ！
tags: [GKState, iOS, 架構, 狀態機, GKStateMachine]

---

# 善用狀態機架構　大幅簡化 View Controller ！

###### tags: `狀態機` `架構` `iOS` `GKStateMachine` `GKState`

## 實作 [appcoda:善用狀態機架構　大幅簡化 View Controller ！](https://www.appcoda.com.tw/view-controller-state-machine/)

[範例程式](https://github.com/JeromeTW/HelloGKStateMachine)
1. [News API](https://newsapi.org/)
1. UniversalVC
1. ViewController with GKStateMachine
1. ViewController with GKStateMachine in my way(my style)(Use Storyboard)

`GKStateMachine 與 GKState 都是 NSObject 的子類型，這代表了它們都有能力去套用 UITableViewDataSource 等協定，分擔 Controller 的工作。GKStateMachine 是一個具體類型，唯一職責就是擔任狀態之間的切換者，通常不需要去建立子類型；而 GKState 則是一個抽象類型，所有方法都是設計來被覆寫的，所以要寫子類型才有用。`

![](https://i.imgur.com/vyWrROy.png)


## MVC 常見問題:
![](https://i.imgur.com/7wcpTgx.png)

```
showHUD 可能放在 didPressButton 或者 loadArticles.

@objc func didPressButton(_ sender: UIButton) {
    // Big function with many responsability, and we want to reuse this function in many different places.
    showHUD()
    //....
    loadArticles()
  }
```

![](https://i.imgur.com/tfuJvHp.png)


### 總結
當然，最後還是要不免俗的呼籲一下，狀態機並不是萬靈丹。它雖然強大，但也是讓你的 app 架構又多了一個層架 (overhead)。如果你的物件本身狀態已經很簡單的話，那用狀態機的意義也就不大。熟悉並活用抽象、封裝、組合優於繼承 (composition over inheritance)、單一真值來源 (single source of truth) 等概念才是優良程式架構的不二法門，而狀態機只是其中的一種工具罷了。

### 參考連結
* [appcoda:善用狀態機架構　大幅簡化 View Controller ！](https://www.appcoda.com.tw/view-controller-state-machine/)
* [GKStateMachine 官方定義](https://developer.apple.com/documentation/gameplaykit/gkstatemachine)
* [GKState 官方定義](https://developer.apple.com/documentation/gameplaykit/gkstate)
* [Dispenser: GameplayKit State Machine Basics 官方 Sample Code Swift3](https://developer.apple.com/library/archive/samplecode/Dispenser_GameplayKit/Introduction/Intro.html#//apple_ref/doc/uid/TP40016460)
* [Raywenderlich :Practical State Machines with GameplayKit(牽扯到 Coordinate 架構,我覺得主題有些混淆)](https://www.appcoda.com.tw/view-controller-state-machine/)