Coordinator 系列之初識 Coordinator 模式

翻譯原文ios


視圖控制器最大的問題之一是它們混合了您的導航邏輯、視圖邏輯和業務邏輯。ui

當一個 tableViewCell 被選中時,代理方法一般會是這樣的:spa

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {  
	id object = [self.dataSource objectAtIndexPath:indexPath];  
	SKDetailViewController *detailViewController = [[SKDetailViewController alloc] initWithDetailObject:object]  
	[self.navigationController presentViewController:detailViewController animated:YES];  
}
複製代碼

三行簡單的代碼作了三件事:獲取模型對象、建立視圖控制器、展現視圖控制器。在一個至關簡單的 App 中,這樣徹底沒有問題。每一個視圖控制器大機率只會使用一次。像這樣耦合它們並非危險的操做。然而當你的App日益複雜,一個控制器可能會在一個新的地方被使用。也許會被適配到iPad上,也許在APP extension中,也許是一個老業務的新邏輯。

若是導航邏輯被寫在了視圖控制器中,那麼這個控制器就無法不經過拖拽全部的代碼來複用它已有的視圖顯示邏輯。不要忘記,視圖控制器的基類是以UI爲前綴,這說明它是視圖對象,處理用戶邏輯超出了它的能力範圍。

在上面的代碼中,視圖控制器知道了如何建立整個業務流中的下一個對象以及如何顯示它。在第三行代碼中,它告訴它的父視圖控制器要作什麼,這顯然是顛倒黑白的(譯者:至關於兒子指揮老子作事情)。更糟糕的是,相似的代碼分佈在多個視圖控制器中,每一個視圖控制器只知道如何執行下一步。

我過去認爲視圖控制器是 App 中最上層的東西,是知道如何運行整個流程的東西。然而,最近我發現讓一個更高級別的對象來指揮視圖控制器有不少好處,這個對象的做用是引領和管理其權限內的全部視圖控制器。

我把這些對象叫作 Coordinators,或者也能夠叫作 Directors。要真正很好地執行此模式,您須要一個高級協調器來指導整個應用程序(有時稱爲應用程序控制器模式)。AppDelegate持有AppCoordinator,每一個協調器擁有一組子協調器。特別是若是你有不止一個控制器,如在標籤欄應用,每一個導航控制器有本身的協調器,用於指導其行爲和導航流。能夠爲註冊或建立內容等特定任務建立更多的子協調器。每一個協調器由其父協調器建立。在開發過程的早期使用此模式,即便在單步任務(如身份驗證)中也頗有用。

協調器是一個 PONSO(Plain Old NSObjects)純粹的NSObject對象。對於 Instagram 的照片創做流程,咱們可使用PhotoCreationCoordinator。app協調器能夠生成一個新視圖,並將根視圖控制器傳遞給它,這樣它就能夠在流中呈現第一個視圖控制器。

- (void)beginPhotoCreationProcess {  
	PhotoCreationCoordinator *coordinator = [[PhotoCreationCoordinator alloc] initWithRootViewController:self.rootViewController delegate:self]  
	[self.childCoordinators addObject:coordinator];  
	[coordinator beginPhotoCreationProcess];  
}
	
- (void)photoCreationCompletedSuccessfully:(PhotoCreationCoordinator *)coordinator {  
	[self.childCoordinators removeObject:coordinator];  
}
	
- (void)photoCreationCanceled:(PhotoCreationCoordinator *)coordinator {  
	[self.childCoordinators removeObject:coordinator];  
}  
複製代碼

協調器的-beginPhotoCreationProcess方法如今能夠建立一個新的照片選擇視圖控制器,並根據須要配置它。協調器能夠成爲照片選擇視圖控制器的委託,以便它能夠在顯示下一步的時候獲得通知。流程中的任何視圖控制器都不須要知道任何其餘視圖控制器。每一個視圖控制器都是一個孤島。

業務邏輯(例如發佈照片)被包裝在屬於其本身的對象中,能夠根據須要向上挪到協調器或向下挪到模型。不管哪一種方式,它都從視圖控制器移出去了。將其挪到協調器是很是好的,由於協調器已經充當代碼不一樣部分之間的粘合劑。

將流提取到協調器中有無數好處。視圖控制器如今能夠專一於將模型綁定到視圖。能夠更容易地重用它們,好比在擴展或非綁定應用程序中,而不須要複雜的條件來管理不一樣的上下文。A/B 測試很是簡單,只需建立一個不一樣的協調器對象並使用它來啓動流程。導航邏輯如今有了家,有家的感受真的很好。

視圖控制器的初始化也被提取出來了。這一點不容忽視。初始化老是一個看起來簡單實則更復雜的任務,須要大量關於類和配置的知識,咱們將它轉移到一個更好的地方,在那裏能夠作出更明智的決定。

不知不覺協調器對象就會持有許多分離的狀態,換句話說,特別是對於iPhone應用程序,隨時都只能看到一個屏幕。這使它們水到渠成地成爲使用狀態機來管理其全部數據的合適場所。(譯者注:狀態機的最佳實現就是單向數據流,以後譯者會引伸出來新的模式)。

蘋果喜歡讓視圖控制器成爲 iOS 世界的中心。這一點在 iOS 8 的新UISplitViewController api以及 storyboard segue等 Interface Builder 組件中很明顯。不幸的是,以視圖控制器爲中心的應用程序開發方法是不可伸縮的。協調器是一種很好的方法,能夠將代碼隔離成小的、易於替換的塊,成爲解決視圖控制器問題的解決方案的一部分。

相關文章
相關標籤/搜索