iOS 分類(category)、類擴充套件(extension)、協議(protocol)
分類 category
使用場景分析
1.擴充套件已有的類
有大量的子類,需要新增公用方法,但又無法修改它們的父類的情形(如系統類)。
一般是大量的功能程式碼已經形成,使用子類需要新增新類的標頭檔案等。分類只能新增方法,不能新增屬性。(下文會提到如何新增屬性)
2.使用父類私有方法
已經存在了大量的子類方法,但是又無法修改他們的父類,比如系統自帶的類新增類擴充套件方法。在子類中宣告父類類別後,即可通過編譯。
蘋果會拒絕使用系統私有API的應用上架,如果需要呼叫私有API,還是要謹慎處理,嘗試用其他方法替代。
新增分類(Xcode 9.4.1)
1-1.png
1-2.png
1-3.png
1-4.png
分類使用過程步驟:(包含程式碼)
// .h檔案
#import <UIKit/UIKit.h>
@interface UIButton (tg)
- (void)eat;
@end
// .m檔案
#import "UIButton+tg.h"
@implementation UIButton (tg)
- (void)eat {
NSLog(@">>>eat");
}
@end
// 使用場景 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.frame = CGRectMake(100, 100, 50, 50); [btn eat]; [self.view addSubview:btn]; }
分類優先順序執行
① 本類和分類的話,分類優先於本類的方法
② 如果有兩個分類中都實現了相同的方法,執行順序是 targets->Build Phases->Complie Source,順序是從上到下。
給分類新增屬性
#import <UIKit/UIKit.h>
@interface UIButton (tg)
//給分類新增一些屬性
@property (nonatomic,copy) NSString * name;
- (void)eat;
@end
static const void * tg_name = @"dog";
// .m檔案需要先匯入<objc/runtime.h>
//屬性的set和get方法的實現
#pragma mark - 字串型別的動態繫結
/*
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC retain
OBJC_ASSOCIATION_COPY_NONATOMIC copy
OBJC_ASSOCIATION_RETAIN
OBJC_ASSOCIATION_COPY
*/
//set方法的實現
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, tg_name, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
//get方法的實現
- (NSString *)name{
return objc_getAssociatedObject(self,tg_name);
}
類擴充套件(extension)
類擴充套件(extension)作用分析
類擴充套件可以理解為Category的其中的一種,可以用來給當前類新增屬性和新方法。
類擴充套件使用過程步驟:(包含程式碼)
// 類擴充套件是寫在.m中的,相信你一看就知道
@interface ViewController ()
@property (nonatomic, strong) NSString *boss;
- (void)bossAngry; // 擴充套件方法
@end
類擴充套件優缺點分析
① 類擴充套件的屬性和方法都是私有的,也可以定義在.h中,這樣就是共有的,類擴充套件中的方法是一定要實現的方法。Category沒有這個限制。
2-1.png
category、extension異同點分析
1、分類(category)
① category只能新增“方法”,不能新增成員變數。
② 分類中可以訪問原來類中的成員變數,但是隻能訪問@protect和@public屬性。
③ 新增方法加上字首,新增方法會覆蓋父類的同名方法,可以防止意外覆蓋,也防止被別人覆蓋。
④ 分類中新增的成員變數,要通過getter、setter方法進行新增。
類擴充套件(extension)
① 類擴充套件的屬性和方法都是私有的,也可以定義在.h中,這樣就是共有的,類擴充套件中的方法是一定要實現的方法。Category沒有這個限制。
協議 (protocol)
協議的使用場景
協議是委託別人做自己想做的事情,可以用來傳值,或者用來監聽、通知。
代理(delegate)要用assign,防止迴圈引用。
協議的使用過程步驟:(包含程式碼)
// 代理的.h檔案
#import <UIKit/UIKit.h>
@protocol TGEatDelegate <NSObject>
- (void)eatEgg;
- (void)eatFruit;
@end
@interface TGEat : UITableViewCell
@property (nonatomic, assign) id <TGEatDelegate> delegate;
@end
// 代理.m檔案中用到
if ([self.delegate respondsToSelector:@selector(eatEgg)]) {
[self.delegate eatEgg];
}
// 需要接收資訊,監聽的類
// 新增標頭檔案,引用代理<TGEatDelegate>
- (void)eatEgg {
NSLog(@"who care!");
}