<b>本文講的是[譯]iOS開發者在Swift中應避免過度使用,</b>
<b></b>
為了達到本文的目的,我簡化了工作中項目的代碼,但所有核心的思想都保留着。一種我經常在swift裡用的模式是:為了重用的配置寫protocols(協定)和extensions(擴充),特别是有Uikit的時候
假設我們有一組視圖控制器,每個控制器都需要一個 view model 和 一個“取消”按鈕。每一個控制器需要各自響應
“cancel”按鈕的點選事件。我們可以這樣寫:
如果就寫成這樣,那每個控制器都需要自己去添加和寫一個一樣的取消按鈕。這樣就會有很多一樣的代碼。我們可以通過擴充(用老的 <code>Selector("")</code> 語句)來解決:
現在每個符合協定的控制器都可以通過在<code>viewDidLoad()</code>裡調用協定的<code>configureNavigationItem()</code> 方法來配置取消按鈕,是不是好多了~我們的控制器看起來是這樣的:
這僅是一個簡單的例子,但我們可以想象通過這個方式制造更多複雜的配置。
把以上代碼段更新到 Swift 2.2後,是這樣的:
但現在我們有了個問題,一個新的編譯錯誤
因為一系列的原因, 在原始的<code>ViewControllerType</code>協定中,我們并不能簡單的給這個方法添加一個<code>@objc</code>修飾符。如果我們這麼做了,那麼所有的protocol都需要用<code>@objc</code>來标記,這将意味着:
所有這個protocol的父protocol都需要用<code>@objc</code>來标記。
所有繼承自這個protocol的protocol都會被自動添加<code>@objc</code>。
我們在protocol中的結構體(<code>ViewModel</code>)不能用Objective-C來表示。
我們在這的例子很簡單,但是想象一下更複雜的類依賴關系圖,大量使用Swift的值類型和當這個協定處在多個協定的中間層時。把引入<code>@objc</code>作為解決方案真是app的末日。如果我們這樣做,<code>@objc</code>這種做法會讓我們的Swift代碼毫無美感并變得亂糟糟。這會毀了所有的東西。
但是希望還是有的。
我們大可不必讓為了讓我們的Swifit代碼能使用Objcetive-C的文法而使用<code>@objc</code>。
我們可以把protocol分解成多個protocol來去除<code>@objc</code>,然後我們再重組這些protocol。事實上,我們可以讓編譯器順利編譯和避免更改任何視圖控制器的代碼。
第一步,我們把protocol拆成2個。<code>ViewModelConfigurable</code> 和 <code>NavigationItemConfigurable</code>。把<code>ViewControllerType</code>裡的extension放到<code>NavigationItemConfigurable</code>。
最終,我們可以把原<code>ViewControllerType</code> protocol定義成<code>typealias</code>。
和遷移到Swift2.2之前比一切都很正常,而且我們定義的原視圖控制器也沒有發生任何改變,沒有東西被破壞。如果你曾經遇到類似的情況,或者你也想阻止<code>@objc</code>帶來的破壞(你應該這麼做),我強烈建議采用這個政策。
現在的代碼,我還是覺得有點不爽,當然,針對這個問題,這就是最Swift化的答案。當Xcode突然開始提示你并且很快的應用它的修複方案依然會把所有都破壞掉。特别是當Xcode提供的修複方案正中你下懷的時候,這個時候,上面說的到的這類解決方案并不能立即很清楚。
最後,在做了以上那些更改之後,我意識到總的來說這其實是一個很好的解決方案。。沒有什麼理由在一個地方隻用一個協定。像<code>ViewModelConfigurable</code> 和 <code>NavigationItemConfigurable</code>這兩個協定分工明确。把不同的協定組合在一起始終都是最優雅、最适當的設計。
作者:donghuan1
連結:http://www.jianshu.com/p/b50a8ed6a00b
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
<b>原文釋出時間為:2016年06月27日</b>
<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>