2-3 iOS 分類(Category)& 類擴充套件(Extension)
阿新 • • 發佈:2019-02-12
分類(Category):
分類是OC中的一個特有語法,它表示一個指向分類結構體的指標。一般情況下,我們只能新增給分類增加方法,而不能增加例項變數(成員變數)。分類的格式:
@interface 待擴充套件的類(分類的名稱)
@end
@implementation 待擴充套件的類(分類的名稱)
@end
分類的使用場景:
我們知道,給一個A類新增方法,簡單粗暴的方式就是直接在A類在.h中宣告,.m中實現該方法。但是這樣做,有時候不便於專案的管理和移植,試想,如果一個類有雜七雜八幾十個不同的方法糅合在一個.h中。要是以後我們想要呼叫其中某一個方法,還得把整個移植過來,或者把方法扣出來。這多惱火。 蘋果為了解決這些問題,特地引入了分類這個概念。我們可以專門用一個資料夾管理這些分類。比如UIImage資料夾下面,UIImage+GIF,UIImage+Cache。。。等等。很直觀,也更便於專案的管理與移植。為分類新增屬性:
我們發現,分類所指向的結構體中根本就沒有屬性列表。所以,就算是你強行用@property,編譯器也不會給你自動生成setter/getter方法,也不會生成私有成員變數。 但是,有些情況下,我們在給分類新增的方法中,如果有屬性存在的話,會便利很多。比如,我想給一個UIButton類擴大點選區域,需要上下左右四個可變數值,用屬性的話要便利很多。但如何去給分類新增屬性呢? 如果研究過runtime相關的程式碼,相信你肯定知道關聯物件這一說法。如果你暫時還不瞭解,可以看看我之前的一篇博文runtime動態關聯物件,在此我就只簡單描述一下。定義靜態變數,用其地址作為關聯物件的keystruct objc_category { char * _Nonnull category_name OBJC2_UNAVAILABLE; //分類名稱 char * _Nonnull class_name OBJC2_UNAVAILABLE; //要擴充套件的類名 struct objc_method_list * _Nullable instance_methods OBJC2_UNAVAILABLE; //例項方法列表 struct objc_method_list * _Nullable class_methods OBJC2_UNAVAILABLE; //類方法列表 struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE; //分類實現的協議 }
設定關聯物件#import <objc/runtime.h> @implementation UIButton (EnlargeTouchArea) static char topNameKey; static char rightNameKey; static char bottomNameKey; static char leftNameKey;
- (void)addIncreaseTapAreaWithTop:(CGFloat)top buttom:(CGFloat)buttom left:(CGFloat)left right:(CGFloat)right {
objc_setAssociatedObject(self, &kTopNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &kRightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &kButtomNameKey, [NSNumber numberWithFloat:buttom], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &kLeftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
獲取關聯物件
NSNumber *top = objc_getAssociatedObject(self, &kTopNameKey);
NSNumber *right = objc_getAssociatedObject(self, &kRightNameKey);
NSNumber *buttom = objc_getAssociatedObject(self, &kButtomNameKey);
NSNumber *left = objc_getAssociatedObject(self, &kLeftNameKey);
以上,就是如何動態為分類新增屬性。
類擴充套件(Extension):
類擴充套件其實也是分類的一種,我們應該說是時時刻刻都在打交道。類擴充套件和分類的區別就在於有沒有分類的名稱,以及類擴充套件是編譯期屬性,分類屬於執行時屬性。
類擴充套件的實現:
@interface ExtionsionClass
@property (nonatomic,copy) NSString *name;
- (void)eat;
@end
使用類擴充套件注意兩點: 1.一般類擴充套件寫在依託的對應類的.m中,私有屬性寫到擴充套件中。2.類擴充套件中方法的實現,需要在依託的對應類的.m中實現(區別於分類,沒有@implementation部分)。如果沒有實現已經聲明瞭的方法,編譯器會報警(區別於分類,分類這種情況不會報警告。這就是我說的編譯期和執行時的差別)。
這兩種如何合理使用,看各人的愛好以及對應業務的處理吧。