iOS知識梳理 - category和extension
category和extension
category的能力
category主要作用是在不改變原有類的前提下,動態地給這個類新增一些方法。
蘋果早年一份官方文件 指出,category主要有三種用途:
- 給現有的類新增方法;
- 將一個類的實現拆分成多個獨立的原始檔;
- 宣告私有的方法。
這裡我們逐個分析。
1. 給現有的類新增方法
常見。比如給UIColor新增一些跟16進位制色值互轉的方法。如下:
@interface UIColor (Hex) + (UIColor*) colorWithHex: (NSUInteger) hex; @end @implementation UIColor (Hex) + (UIColor*) colorWithHex: (NSUInteger)hex { CGFloat red, green, blue, alpha; red = ((CGFloat)((hex >> 16) & 0xFF)) / ((CGFloat)0xFF); green = ((CGFloat)((hex >> 8) & 0xFF)) / ((CGFloat)0xFF); blue = ((CGFloat)((hex >> 0) & 0xFF)) / ((CGFloat)0xFF); alpha = hex > 0xFFFFFF ? ((CGFloat)((hex >> 24) & 0xFF)) / ((CGFloat)0xFF) : 1; return [UIColor colorWithRed: red green:green blue:blue alpha:alpha]; } @end
2. 將一個類的實現拆分成多個獨立的原始檔
這種在小專案中可能少見一些,但在大型專案中比較多。比如某日活過億的iOS軟體,其配置系統中大約有400份配置,很多功能根據配置的內容會有不同的表現,不同使用者拉取不同內容的配置。
這400份配置會在使用者首次登陸時全量拉取,在以後登陸時增量拉取。注意這都是一條請求帶回來的。
如果把這400份配置的解析處理都寫到一個檔案裡,這個檔案顯然會膨脹到一個很恐怖的地步。最好的方式就是讓每個業務新增自己的分類,在分類中處理自己的配置內容。
當一個類可能過於膨脹的時候,通過分類進行拆分是比較好的做法。
3. 宣告私有的方法
一開始看到這個玩意兒的時候我簡直一頭霧水。
方法不想暴露出去就不要宣告不就好了嘛???搜了半天才理清楚裡面的來龍去脈。
最早的上古年代,那時候objc所有的方法都是要宣告的,無論是是否想要暴露出去。
不想暴露出去的方法就需要一個內部category來進行宣告。
如下:
// MyClass.m @interface MyClass (privatemethods) - (void)myPrivateMethod; @end @implementation MyClass - (void)myPrivateMethod { // Implementation goes here } @end
過了一陣子,官方覺得這樣寫有點累贅。於是做了一丟丟簡化:
// MyClass.m @interface MyClass () - (void)myPrivateMethod; @end @implementation MyClass - (void)myPrivateMethod { // Implementation goes here } @end
在這種情況下可以去掉category的名字,這種語法被稱為Extension 。
再後來,進一步簡化,私有方法不再需要定義了,不過私有屬性和成員變數仍然放在extension中。
// MyClass.m @interface MyClass () { BOOL _isFat; } @property (nonatomic,assign) BOOL isTall; @end @implementation MyClass - (void)myPrivateMethod { // Implementation goes here } @end
目前為止,這種寫法是我見過的最廣泛的寫法。
但是其實更新的語法推薦把成員變數放到implentation部分
// MyClass.m @interface MyClass () @property (nonatomic,assign) BOOL isTall; @end @implementation MyClass { BOOL _isFat; } - (void)myPrivateMethod { // Implementation goes here } @end
不過很少看到這麼寫了。
結語
本文主要挖了挖語法,
TODO:底層實現以後再runtime部分去做梳理。