1. 程式人生 > >iOS 分類(category)、類擴充套件(extension)、協議(protocol)

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!");
}