【iOS開發】ViewController減負記錄

KyXu發表於2016-04-16

前言

最近在重構一個以前寫的老專案,在嘗試給之前的 ViewController 減負,儘量抽離程式碼到其他檔案。
想記錄一些東西,看看以後返回來再看能不能有更好的想法;而現在,可以作為一個檢驗當前程式碼是否需要優化的一個標準。


整合常量

以前喜歡在 ViewController 的頂部(class 外面)寫一些全域性變數,這樣雖然可以寫一次建立的程式碼,就可以在整個專案的任意地方使用。但是,基本上你不可能只有一個 ViewController,有了這種習慣之後,會讓全域性變數沒有邏輯地分散在不同的程式碼檔案裡,不易於管理(甚至可能會出現同一個東西以不同的名字被建立了多次的情況),而且程式碼可讀性會嚴重降低(因為你看見這個變數的時候,你可能並不知道它是全域性的)。

解決起來其實很簡單,我當前這個專案的縮寫是 GM,於是我建了一個叫 GMConstants 的 Class,把所有之前的全域性變數都放到這裡,寫成 <code>static let</code> 的形式。(除非你真的知道這樣沒問題,否則不建議寫 <code>static var</code>,或建立 GMVariables Class,這樣會導致你使用這些量的時候,依然不知道具體這些是什麼,因為它們可能被更改過)

比如之前我設定了我這個 App 中使用的所有的灰色都應該是一樣的,我寫了一個 gmGreyColor 的常量,使用的時候,你可能並不記得這麼一個東西是全域性的,並且擔心除了灰色,還有什麼顏色,是不是還有個 gmBlackColor?甚至你可能寫了一個意義相同的 gmGrayColor,僅僅是因為 grey 和 gray 同義。而現在,你的使用方式應該是 <code>GMConstants.greyColor</code>——一看便知是什麼意思,而且按住 cmd 鍵,滑鼠左擊 GMConstants 關鍵詞,你還可以看見你到底建立了幾個類似這樣的顏色。

當你想寫全域性變數,或者發現某個區域性變數,在不同的地方被多次使用的時候,就該考慮這個問題了。


布林標記

剛剛提到不建議以整合常量的方式來整合變數,不過後續又發現之前會用這樣一種方式來處理邏輯:先寫一個值為 <code>false</code> 的布林變數,以此作為一種標記,後續根據情況來不斷地修改該值為 <code>true</code> 或者 <code>false</code> ,來判斷某些語句是否應該執行。

雖然目前認為這種方式並不是優雅的寫法,因為這樣一個布林標記的作用範圍太大了,雖然寫程式碼的時候知道,某種情況 <code>true</code>,另一種情況 <code>false</code>,但以後修改的時候,就要求程式設計師有全域性觀才能嘗試修改或移除這個標記。

暫時沒有想到很好的修改方法,但是認為這種情況下,可以像之前整理 <code>static let</code> 一樣來以 <code>static var</code> 的形式來整理這些布林型別的標記,可能取 class 名為 GMMarks。

另外還可以自定義這些標記的 setter,比如

static var imageSelected:Bool = false

我們可以這樣自定義 setter:

class func selectImage() {
    GMMarks.imageSelected = true
}
class func deselectImage() {
    GMMarks.imageSelected = false
}

語義更清晰易懂


UIView 耦合

self.view.addSubview(view1)
self.view.addSubview(view2)
self.view.addSubview(view3)

假如說在 ViewController 裡面看到上面這樣的程式碼,同時發現 view1、view2、view3 之間就是簡單的一層一層疊加而已,那麼我們或許可以向之前一樣建一個叫做 GMViews 的 class,然後把這三個 view 的建立都放在

class func xxView (frame frame:CGRect) -> UIView

這樣一個方法裡面,使用時也很簡單

let xxView = GMViews.xxView(frame: xx)
self.view.addSubView(xxView)

這個時候一定要注意,之前三個 view 在 ViewController 裡面建立時,frame 是根據 self.view 這個 view 來寫的,frame.origin 是一個 CGPoint,它表示的是相對於父級 view 的相對位置,而不是相對於你的 App 介面的絕對位置,所以抽離這部分程式碼的時候,確保你的各個 view 的 frame 寫對(在支援橫屏的時候,是不是還涉及其他問題)。


抽離方法命名問題

MVC 令人詬病的一點是,以前寫在 Controller 裡面的業務邏輯很臃腫,現在加個 <code>func</code> 關鍵字就抽離到 Model 裡面,導致 Controller 不臃腫了,Model 反倒臃腫了。

所以如果想要從之前臃腫的 ViewController 裡面抽離到程式碼到新的類,一定要注意 Model 的命名問題。

比如說我現在要清理快取,清理快取這種事情應該說和當前的 ViewController 是沒什麼耦合性可言的,完全可以把這部分程式碼剝離出來,那麼如果這時候我根據清理的具體內容不同,抽象出了三個函式:

func clear1() {}
func clear2() {}
func clear3() {}

如果直接粗暴地把這三個方法填到一個叫做 GMTools 的類裡面,把這些方法都加上 <code>class</code> 關鍵字,那麼以後這個類會越來越雜亂,這和之前沒什麼分別。

較好的做法應該是把這個類叫做 GMClear,而且儘量呼叫方法的時候,讓方法體內部的邏輯和現在的這個 App 本身沒太大關係,把和現在的 App 有直接關係的部分作為引數,讓使用者傳參呼叫。

這樣下來,或許你可以在這個專案結束的時候,擁有幾個可能叫 GMClear、GMSave、GMShare 的類,而且這些類裡面的方法和你現在這個 App 沒有太多直接聯絡,那麼下一個專案用到這些東西,直接把程式碼檔案複製過去就可以了。


相關文章