還記得在 2017 的時候,**@khanlou** 曾經給過一個 talk,是關於 Coordinator 的 talk。當時的我也還是個小菜雞,只要看到各種關於 architecture 的東西都會莫名興奮。
這個 talk 想要解決的是當 app 越來越大、越來越複雜的時候的一個處理方式。當時 Coordinator 被提出的時候也並沒有太多人去實作出來,比較偏向是一個概念,以至於小菜雞如果就會開始 google 看看有沒有 library 可以幫我們把 coordinator 實作完,可以讓我們直接套到我們 app 上的 solution 呢?想當然是沒有。於是把 app 改成使用 coordinator 架構這件事就這樣被擺在一旁。
接著過了快一年,剛好公司有一個專案需要從頭開始,這個時候是最適合導入各種你想要、你喜歡的架構的時候。於是選定好 MVVM + Coordinator 當成 project base architecture,開始了 Coordinator 這個不歸路了。
這邊直接舉一些當時使用 Coordinator 所遇到的問題
.start() 方法在嘗試了 Coordinator pattern 一年,也就是一個專案從 0 到 1 之後,這些問題是我所遇到,想要嘗試解決、或者找到更好解法的一些問題點。當時剛好看到 Khoa 在 github 上提了這個 issue,讓我想嘗試使用 FlowController,也剛好又有一個新專案可以讓我嘗試 FlowController + MVVM + Combine + Input & Output data binding pattern(是不是腦洞大開啦)。
不過這裡我們還是圍繞在 FlowController 就好,因為你會漸漸發現
不管你用的 architecture 再怎麼華麗花俏,最終還是得回歸 SOLID 原則,好讀好維護,寫別人讀得懂的程式碼才是最重要的。
Architecture 終究只是 architectural pattern。
我們可以先看看 FlowController 大致上長怎樣:
struct DependencyContainer: AuthServiceContainer, PhoneServiceContainer, NetworkingServiceContainer,
LocationServiceContainer, MapServiceContainer, HealthServiceContainer {
let authService: AuthServiceProtocol
let phoneService: PhoneService
let networkingService: NetworkingService
let locationService: LocationService
let mapService: MapService
let healthService: HealthService
static func make() -> DependencyContainer {
// Configure and make DependencyContainer here
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var appFlowController: AppFlowController!
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
appFlowController = AppFlowController(
dependencyContainer: DependencyContainer.make()
)
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = appFlowController
window?.makeKeyAndVisible()
appFlowController.start()
return true
}
}
跟 Coordinator 不一樣的點我們可以在這裡就看出來,我們並不需要將 window 丟給 AppCoordinator 去控制,只要將 AppFlowController 加到 window 上,因為他本來就是 UIViewController based,所以保有 UIResponder chain 特性,可以直接顯示 AppFlowController 上第一個 view。
如此一來,我們就不需要將 window 在 coordinator 間互相傳遞,而是只要在 AppFlowController 中控制好我們的 child vc 即可。 (問題點 2 解決)