亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

使用 FLOWCONTROLLERS 改進IOS應(yīng)用架構(gòu)

wmui / 3337人閱讀

摘要:每個都定義了可以監(jiān)聽它們的行為的接口如果需要支持多個設(shè)備和不同的展示方式,程序中會有其他類,沒有意大利面條的代碼。使用這樣的架構(gòu)的好處是顯而易見的界面之間沒有依賴關(guān)系。更干凈的代碼,我看到的唯一意大利面條代碼是我做的。

引言

開發(fā)iOS應(yīng)用時,現(xiàn)在更應(yīng)該避免在一個視圖控制器中直接展示其他視圖控制器。

為什么?

問題

現(xiàn)代應(yīng)用程序通常需要需要支持以多種方式展示相同的視圖控制器。例如,在iPhone上你 push 一個新的視圖控制器,但是在 iPad 上,你會把它嵌入另一個視圖控制器或者用 popover 展示出來。

另外,很多情況下,你可能想在不同的情景中重用同一個視圖控制器。如 UIImagePickerController 可以在多個地方以不同的方式展示出來。

視圖控制器應(yīng)該不依賴于他們的展示樣式,這就是 SizeClasses 出現(xiàn)的原因之一。

如果你從其他 VCs / ViewModels 展示視圖控制器,你將寫出來一堆if語句,你的代碼將變成條件大面條(big spaghetti of conditions)

我作為一個顧問,經(jīng)常需要參與審查項目,并幫助團隊制訂更干凈的解決方案。

我看到過很多的意大利面條代碼。下面這個就是相當糟糕的一個例子,但是還沒有接近我見過最差的:

func doneButtonTapped() {
  let vc = NextViewController(prepareNeccesaryState())

  if Device.isIPad() {
    navigationController.pushViewController(vc, animated: true, completion: nil)
  } else {
    var nav = UINavigationController(rootViewController: vc)
    nav.modalPresentationStyle = UIModalPresentationStyle.Popover
    var popover = nav.popoverPresentationController
    popoverContent.preferredContentSize = CGSizeMake(500, 600)
    popover.delegate = self
    popover.sourceView = self.view
    popover.sourceRect = CGRectMake(100, 100, 0, 0)

    presentViewController(nav, animated: true, completion: nil)
  }
}

這個幼稚的實現(xiàn)存在很多問題:

不必要的依賴 —— 一個視圖控制器不需要知道另一個

可重用性差

面條代碼,如果你的應(yīng)用需要以不同的方式展示視圖 - 你需要寫大量的控制流。

單例是誘人的,因為它們讓你更容易編寫代碼。

測試更難,你的VC / VM會有很多的副作用。

我們怎樣才能解決這個問題? 清理你的 ViewControllers / ViewModels

這可以應(yīng)用到 MVVM,MVC 和許多其他的常見模式。當我談到 VC / VM,思考一下你現(xiàn)在正在使用的那一個。

讓我們使用代理或者基于 block 的接口,而不是對相關(guān)的控制器硬編碼,來擺脫所有的依賴關(guān)系。

class MyViewController {
  let onDone = (Void -> Void)?

  func doneButtonTapped() {
    onDone?(prepareNeccesaryState())
  }

}

ViewController / ViewModel 應(yīng)該:

不能引用其他界面

不使用任何 UIKit presentation 類或類似 UINavigationController 或 presentViewController 的方法

有允許其他的對象通過注冊來獲知這個功能正在運行的接口,例如,代理或 block

不引用任何單例,稍后你會看到用我的做法是如何容易實現(xiàn)這一要求的。

這個時候,我們已經(jīng)提高了可測試性,因為我們現(xiàn)在可以測試我們的接口是否被觸發(fā)了,且無需副作用。偽代碼:

let vc = createVC()
var executed = false
vc.onDone = {
  executed = true
}
//! add code here to trigger done state
expect(executed).toEventually(beTruthy())

但是,我們?nèi)绾螀f(xié)調(diào)我們的應(yīng)用程序視圖控制器?

介紹 FlowControllers

一個 FlowController 是一個簡單的對象,它將管理你的應(yīng)用程序的一部分,我喜歡把它看成用例的一個子集。

FlowController 的三個主要角色是:

為視圖控制器配置特定上下文 - 例如分別為從應(yīng)用 CreatePost 界面彈出的 ImagePicker 和改變用戶頭像時彈出的設(shè)置不同的配置

監(jiān)聽每個 ViewController 中的重要事件,并用來協(xié)調(diào)它們之間的流程。

為視圖控制器提供它需要的東西,從而移除VC中的單例

func configureProgramsViewController(viewController: ProgramsViewController, navigationController: UINavigationController) {
    viewController.state = state
    viewController.addProgram = { [weak self] barButton in
        guard let strongSelf = self else { return }
        let createVC = R.storyboard.createProgram.initialViewController!
        strongSelf.configureCreateProgramViewController(createVC, navigationController: navigationController)
        navigationController.pushViewController(createVC, animated: true)
    }
}

常見帶有 FlowControllers 的應(yīng)用架構(gòu)像這樣:

每個應(yīng)用程序都有至少一個 FlowController,Root FlowController 由 AppDelegate 創(chuàng)建。

*實際上是 AppDelegate 中的一個 ApplicationController 創(chuàng)建了它,作為一個經(jīng)驗法則,你永遠不應(yīng)該引??用你的AppDelegate,永遠。*

每個 FlowController 可以有子控制器。

*如果您的應(yīng)用程序具有可被看作是一個整體,需要多個屏幕的用戶故事的一些重要的子集(如創(chuàng)建新的鍛煉計劃),那么你可以為那一部分創(chuàng)建一個新的子控制器,并從主控制器展示它。*

VC / VM 不知道其他 VC / VM。

*這意味著他們可以在任何地方重復(fù)使用,如果一個步驟是從導(dǎo)入用戶照片庫里的東西,你可以在應(yīng)用程序的不同部分重復(fù)使用這段代碼,例如,EditProfile可以使用相同的選擇器選擇用戶頭像。*

流量控制器配置和協(xié)調(diào)不同的界面。

每個 VC / VM 都定義了可以監(jiān)聽它們的行為的接口

如果需要支持多個設(shè)備和不同的展示方式,程序中會有其他 FlowController 類,沒有意大利面條的代碼。

這個想法最初是 Jim 和 Sami 一年前介紹給我的,我們經(jīng)常使用它。

盡管我們的應(yīng)用劇烈改變了3次,我們的架構(gòu)都輕松地應(yīng)對了,我們能夠重復(fù)使用大量的代碼,也有不少控制器不需要任何改變。

使用這樣的架構(gòu)的好處是顯而易見的:

界面之間沒有依賴關(guān)系。

高復(fù)用率。

更簡單的代碼注入并移除了單例。

更干凈的代碼,我看到的唯一意大利面條代碼是我做的。

以更有表現(xiàn)力的方式來導(dǎo)航。

能夠在共用大多數(shù)代碼時對不同的設(shè)備編寫不同的流。

可以輕松分離測試每個 VC / VM,因為一切都可以注入。沒有必要子類化。

現(xiàn)在,在一些架構(gòu)中也有類似的概念,如 VIPER 有路由器。但它們通常是很復(fù)雜的,需要大量的前期成本,以適配到現(xiàn)有的應(yīng)用程序中。

這個方法最棒的地方是它很簡單直觀,立刻就可以(在現(xiàn)有的項目中)使用它,無需等待新項目。它在小型和大型項目的效果一樣好。

不管你使用 MVVM,MVC 還是其他模式,如果應(yīng)用中存在界面跳轉(zhuǎn),不妨試一試。


作者信息

原文作者:Krzysztof Zab?ocki
原文鏈接:http://merowing.info/2016/01/improve-your-ios-architecture-with-flowcontrollers/
翻譯自 MaxLeap 團隊_UX成員:Alex Sun
翻譯首發(fā)鏈接:https://blog.maxleap.cn/archives/879

商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明作者信息與出處。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/11749.html

相關(guān)文章

  • 移動端開發(fā):架構(gòu)那點事!

    摘要:移動精英開發(fā)社群的第期,也是圍繞架構(gòu)這個話題進行討論。本次我們希望結(jié)合實際開發(fā)中遇到的問題,來聊聊移動端的架構(gòu)設(shè)計。這樣的模式改進一些,可能會更適合移動端架構(gòu)。潘衛(wèi)杰之前我們公司移動端的大項目就是插座式開發(fā)的,批量出各個行業(yè)的。 此前,58 同城的技術(shù)委員會執(zhí)行主席沈劍在 OneAPM 的技術(shù)公開課上分享過一個主題,「好的架構(gòu)不是設(shè)計出來的,而是演技出來的」。因為對很多創(chuàng)業(yè)公司而言,隨...

    KnewOne 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<