當學習一個新技能時,比如程式設計語言,我們經常為了能運行,而把所有能用的都揉合在一起。再後來,我們迴歸到這些習慣,並進行重新估計,採用社區中的最佳實務並寫出更好、更有結構化的代碼。
最近,Objective-C語言收到了過多的新特性,但社區的最佳實務還沒持續更新。這就超出了“風格”的範疇,進入了“結構”的領域。
我在最近一段時間裡,審視了我自己的代碼實踐,評估了我可以在哪裡做的更好,所以我想我應該和你們分享我的發現。
歡迎光臨現代Objective-C。
(以上部分感謝Ley翻譯)
訪問執行個體變數(Instance Variable)
唉,執行個體變數。從何說起呢。一句話,執行個體變數很糟。如果你會這樣寫:
別這麼寫了。現在就改。
不要再聲明執行個體變數了,尤其別聲明在標頭檔裡。你應該把它們聲明為property,然後用訊息機制或者“.”來訪問它們。
我之前說過為什麼通過執行個體變數來訪問property沒有明顯的益處。事實上,通過getter/setter方法來訪問有幾個優勢。
真的,沒有理由再去聲明執行個體變數、再去直接存取這些執行個體變數形式的屬性了——除非是在本身覆蓋(override) getter/setter的方法裡,或者在initializer/dealloc 方法裡,取決於你想要代碼有多少防禦性(感謝 Bryan 提供連結)。再除非就是習慣了,但你應該改掉這個習慣。我就改了。
更新: 我找到了官方文檔的一個連結,建議不要在dealloc中調用getter/setter方法。供參考。
那麼唯讀屬性怎麼辦呢?既然沒有setter方法,你不還是需要訪問執行個體變數嗎?好問題。這引出了本文的下一點。
在標頭檔中定義readonly屬性
在你public的介面中要暴露屬性或組件,使用readonly屬性是一個很好的方式。但是如果不直接存取執行個體變數,怎麼設定它們的值呢?答案是在 .m 檔案中定義一個private的class extension。
在你的標頭檔中,聲明如下:
然後,在類的 implementation 檔案中,在以上定義的基礎上,再定義如下:
這樣你就定義了 public 的 getter 和 private 的 setter。可喜可賀!現在你不需要再訪問執行個體變數了。
Schwa 補充了一條建議:
@ashfurrow 回複:《在標頭檔中定義readonly屬性》。我還要加一條,不要在標頭檔裡暴露可變(mutable)對象。順便贊一下,很好的文章。
— Jonathan Wight (@schwa) January 24, 2014
合理地定義 BOOL 類型的屬性
定義屬性時,遵從Apple官方指南總是沒錯的。但我承認,我也不總是看得那麼勤快。要記住,定義BOOL類型的屬性時,要同時手動定義一個getter方法。
@property (nonatomic, assign, getter = isSomething) BOOL something;
如非必要,不要把#import寫在標頭檔裡
我經常在Objective-C新手寫的代碼裡看到這種情況。總體來說,問題在於大多數的#import語句應該唯寫在 .m 檔案裡,而不應該寫在 .h 標頭檔裡。
如下面的例子。
你可以改寫代碼如下,然後在類的 implementation 檔案 yourMyClass.m 中再去 #import MyOtherClass.h 標頭檔。
@class MyOtherClass的寫法是類的前向聲明(forward class declaration)。
這樣寫的益處良多。用類的前向聲明來代替 #import 標頭檔可以提高編譯速度,可以避免迴圈#import,還可以讓你的標頭檔更輕盈——本該如此。
(未完待續)
本文翻譯自:Structuring Modern Objective-C 譯者:Ley,戴倉薯