iOS開發(fā)基礎:如何使用類別(Category)

Objective-C類別也叫分類,是一種不需要繼承即可給類添加方法的語法技術。下面我們來看看如何使用它,以及使用的三種場景。

添加類別

類別聲明模板:

h文件:

@interface ClassName (XSD_CategoryName)
- (void)xsd_addedMethod;
@end

m文件:

@implementation ClassName (XSD_CategoryName)
- (void)xsd_addedMethod {
}
@end

XSD是我自定義的前綴,強烈建議都加上一個自定義的前綴,原因后面詳細敘述。

通過Xcode8添加

選擇Objective-C File
File Type選擇Category
File填入類別名稱,不需要寫類名
選擇文件存放地址
添加好的類別

類別的使用三種場景

1. 擴展已有的類

說到給已有的類添加方法,似乎應該定義一個子類,繼承已有的類,然后添加方法,比如我們常常會自定義UITableViewCell,XSDTableviewCell, showIconWithImage:(UIImage *)image,
但現實情況往往是,大量已有的代碼,都已經使用父類UITableViewCell實現,使用子類需要

  1. 添加新類的頭文件
  2. 所有用UITableViewCell的地方要改為XSDTableviewCell
  3. 調用新方法showIconWithImage:

這第二步,可能涉及數組存儲、參數、局部變量等多個地方的類名修改,如果修改的方法需要跨文件共用,會花費大量時間。
這時用類別,就變?yōu)椋?/p>

  1. 添加新類別的頭文件
  2. 用UITableViewCell直接調用新類別方法

另外,如果已經存在使用XSDTableviewCell的地方,也只需要引入新類別的頭文件,就可以直接調用showIconWithImage:方法了,因為<u>添加到父類中類別方法,會被子類繼承</u>。
因此,

類別特別適合已經存在大量子類,需要添加公用方法,但又無法修改它們父類(如系統(tǒng)類)的情形

2. 引用父類未公開方法

比如父類 XSDLabel:

// XSDLabel.h
#import <UIKit/UIKit.h>

@interface XSDLabel : UILabel

@end
// XSDLabel.m
#import "XSDLabel.h"

@implementation XSDLabel
- (void)giveTextRandomColor {
    self.textColor = [UIColor orangeColor];
}
@end

XSDLabel1繼承自XSDLabel:

#import <UIKit/UIKit.h>
#import "XSDLabel.h"
@interface XSDLabel1 : XSDLabel

@end

現在需要在設置text時,同時設置文字顏色,調用父類的giveTextRandomColor:

#import "XSDLabel1.h"

@implementation XSDLabel1

- (void)setText:(NSString *)text {
    [super setText:text];
    [self giveTextRandomColor];
}

@end

直接編譯會報錯:


編譯器提示找不到父類的方法

在子類中聲明父類類別后,即可通過編譯:

#import "XSDLabel1.h"

@interface XSDLabel (private)
- (void)giveTextRandomColor;
@end

@implementation XSDLabel1

- (void)setText:(NSString *)text {
    [super setText:text];
    [self giveTextRandomColor];
}

@end

類別名private是任意的,但不可以缺省。

請不要亂來:蘋果官方會拒絕使用系統(tǒng)私有API的應用上架,因此即使學會了如何調用私有方法,在遇到調用其它類的私有方法時,要謹慎處理,盡量用其它方法替代。

3. 實現簡單協議

假設我們需要在文字顏色改變時,發(fā)出一個消息,現在修改XSDLabel如下:

#import <UIKit/UIKit.h>

@interface XSDLabel : UILabel
@property(nonatomic) id delegate;
@end

@interface NSObject (XSDLabelDelegateMethods)
- (void)textColorChanged:(UIColor *)colorNow;
@end

增加delegate,聲明為id,表示接受任何類。
聲明NSObject的類別,聲明它實現的方法。

#import "XSDLabel.h"

@implementation XSDLabel
- (void)giveTextRandomColor {
    self.textColor = [UIColor orangeColor];
    [self.delegate textColorChanged:self.textColor]; // 調用代理的方法
}
@end

調用的地方:

#import "XSDLabel1.h"
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    XSDLabel1 *label = [[XSDLabel1 alloc] initWithFrame:CGRectMake(10.0, 40.0, 100.0, 30.0)];
    [self.view addSubview:label];
    label.delegate = self;
    label.text = @"溪石iOS";
}

- (void)textColorChanged:(UIColor *)colorNow {
    NSLog(@"text color changed to %@", colorNow);
}

這里利用了任何類都是NSObject子類的特點,通過添加NSObject的類別,實現了一個“簡單”的代理協議。

對比“正式的協議”,這種協議不需要實現類顯示聲明(如<NSCopying>),不過這里還有個缺點,當ViewController未實現textColorChanged方法時,會引發(fā)崩潰,因此在調用前,需要檢查代理方法是否被實現:

#import "XSDLabel.h"

@implementation XSDLabel
- (void)giveTextRandomColor {
    self.textColor = [UIColor orangeColor];
    if ([self.delegate respondsToSelector:@selector(textColorChanged:)]) {
        [self.delegate textColorChanged:self.textColor];
    }
}
@end

類別的局限

  1. 只能添加方法,不能添加屬性。在類別中聲明的屬性,將無法存取。
  2. 類別中的方法,會覆蓋父類中的同名方法,無法再調用父類中的方法(因為類別中無法使用super),為防止意外覆蓋,總是應該給類別加上前綴。
  3. 不同文件中的同名類別,同名方法,不會報錯,實際執(zhí)行的方法以最后一個加載的文件為準,因此使用前綴防止類別人互相覆蓋。

小結

本文給出了添加類別的方法,Xcode8添加類別的方式與前幾代有所不同。
接著介紹了類別使用的三種情形:

  1. 擴展已有的類。
  2. 引用父類未公開方法。
  3. 實現簡單協議。

最后介紹了類別的局限,主要是存儲空間的分配和名稱沖突,后者可以用加前綴的方式最大限度的避免。

類別是充分利用Objective-C動態(tài)特性的一種方法,用好類別可以實現靈活多樣的編碼。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 136,525評論 19 139
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,592評論 30 472
  • 最近一朋友正準備跳槽,就從各處搜索整理一些基礎,便于朋友復習,也便于自己復習查看. 1. 回答person的ret...
    smile麗語閱讀 1,900評論 0 7
  • 1.項目經驗 2.基礎問題 3.指南認識 4.解決思路 ios開發(fā)三大塊: 1.Oc基礎 2.CocoaTouch...
    扶光啟玄閱讀 5,186評論 0 13
  • 37.cocoa內存管理規(guī)則 1)當你使用new,alloc或copy方法創(chuàng)建一個對象時,該對象的保留計數器值為1...
    如風家的秘密閱讀 954評論 0 4

友情鏈接更多精彩內容