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

Objective-C類別也叫分類妨马,是一種不需要繼承即可給類添加方法的語(yǔ)法技術(shù)。下面我們來(lái)看看如何使用它,以及使用的三種場(chǎng)景弟翘。

添加類別

類別聲明模板:

h文件:

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

m文件:

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

XSD是我自定義的前綴,強(qiáng)烈建議都加上一個(gè)自定義的前綴骄酗,原因后面詳細(xì)敘述稀余。

通過(guò)Xcode8添加

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

類別的使用三種場(chǎng)景

1. 擴(kuò)展已有的類

說(shuō)到給已有的類添加方法趋翻,似乎應(yīng)該定義一個(gè)子類睛琳,繼承已有的類,然后添加方法,比如我們常常會(huì)自定義UITableViewCell师骗,XSDTableviewCell, showIconWithImage:(UIImage *)image,
但現(xiàn)實(shí)情況往往是茁影,大量已有的代碼,都已經(jīng)使用父類UITableViewCell實(shí)現(xiàn)丧凤,使用子類需要

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

這第二步募闲,可能涉及數(shù)組存儲(chǔ)、參數(shù)愿待、局部變量等多個(gè)地方的類名修改浩螺,如果修改的方法需要跨文件共用,會(huì)花費(fèi)大量時(shí)間仍侥。
這時(shí)用類別要出,就變?yōu)椋?/p>

  1. 添加新類別的頭文件
  2. 用UITableViewCell直接調(diào)用新類別方法

另外,如果已經(jīng)存在使用XSDTableviewCell的地方农渊,也只需要引入新類別的頭文件患蹂,就可以直接調(diào)用showIconWithImage:方法了,因?yàn)?lt;u>添加到父類中類別方法砸紊,會(huì)被子類繼承</u>传于。
因此,

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

2. 引用父類未公開(kāi)方法

比如父類 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

現(xiàn)在需要在設(shè)置text時(shí),同時(shí)設(shè)置文字顏色游添,調(diào)用父類的giveTextRandomColor:

#import "XSDLabel1.h"

@implementation XSDLabel1

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

@end

直接編譯會(huì)報(bào)錯(cuò):


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

在子類中聲明父類類別后系草,即可通過(guò)編譯:

#import "XSDLabel1.h"

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

@implementation XSDLabel1

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

@end

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

請(qǐng)不要亂來(lái):蘋果官方會(huì)拒絕使用系統(tǒng)私有API的應(yīng)用上架找都,因此即使學(xué)會(huì)了如何調(diào)用私有方法,在遇到調(diào)用其它類的私有方法時(shí)廊酣,要謹(jǐn)慎處理能耻,盡量用其它方法替代。

3. 實(shí)現(xiàn)簡(jiǎn)單協(xié)議

假設(shè)我們需要在文字顏色改變時(shí)啰扛,發(fā)出一個(gè)消息嚎京,現(xiàn)在修改XSDLabel如下:

#import <UIKit/UIKit.h>

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

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

增加delegate,聲明為id隐解,表示接受任何類鞍帝。
聲明NSObject的類別,聲明它實(shí)現(xiàn)的方法煞茫。

#import "XSDLabel.h"

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

調(diào)用的地方:

#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子類的特點(diǎn)帕涌,通過(guò)添加NSObject的類別摄凡,實(shí)現(xiàn)了一個(gè)“簡(jiǎn)單”的代理協(xié)議。

對(duì)比“正式的協(xié)議”蚓曼,這種協(xié)議不需要實(shí)現(xiàn)類顯示聲明(如<NSCopying>)亲澡,不過(guò)這里還有個(gè)缺點(diǎn),當(dāng)ViewController未實(shí)現(xiàn)textColorChanged方法時(shí)纫版,會(huì)引發(fā)崩潰床绪,因此在調(diào)用前,需要檢查代理方法是否被實(shí)現(xiàn):

#import "XSDLabel.h"

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

類別的局限

  1. 只能添加方法其弊,不能添加屬性癞己。在類別中聲明的屬性,將無(wú)法存取梭伐。
  2. 類別中的方法痹雅,會(huì)覆蓋父類中的同名方法,無(wú)法再調(diào)用父類中的方法(因?yàn)轭悇e中無(wú)法使用super)糊识,為防止意外覆蓋绩社,總是應(yīng)該給類別加上前綴。
  3. 不同文件中的同名類別赂苗,同名方法愉耙,不會(huì)報(bào)錯(cuò),實(shí)際執(zhí)行的方法以最后一個(gè)加載的文件為準(zhǔn)哑梳,因此使用前綴防止類別人互相覆蓋劲阎。

小結(jié)

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

  1. 擴(kuò)展已有的類。
  2. 引用父類未公開(kāi)方法龄毡。
  3. 實(shí)現(xiàn)簡(jiǎn)單協(xié)議吠卷。

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疾渴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屯仗,更是在濱河造成了極大的恐慌搞坝,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魁袜,死亡現(xiàn)場(chǎng)離奇詭異桩撮,居然都是意外死亡敦第,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門店量,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)芜果,“玉大人,你說(shuō)我怎么就攤上這事融师∮壹兀” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵旱爆,是天一觀的道長(zhǎng)霹粥。 經(jīng)常有香客問(wèn)我,道長(zhǎng)疼鸟,這世上最難降的妖魔是什么后控? 我笑而不...
    開(kāi)封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮空镜,結(jié)果婚禮上浩淘,老公的妹妹穿的比我還像新娘。我一直安慰自己吴攒,他們只是感情好张抄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著洼怔,像睡著了一般署惯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镣隶,一...
    開(kāi)封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天极谊,我揣著相機(jī)與錄音,去河邊找鬼安岂。 笑死轻猖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的域那。 我是一名探鬼主播咙边,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼次员!你這毒婦竟也來(lái)了败许?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤淑蔚,失蹤者是張志新(化名)和其女友劉穎市殷,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體束倍,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡被丧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年盟戏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甥桂。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柿究,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出黄选,到底是詐尸還是另有隱情蝇摸,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布办陷,位于F島的核電站貌夕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏民镜。R本人自食惡果不足惜啡专,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望制圈。 院中可真熱鬧们童,春花似錦、人聲如沸鲸鹦。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)馋嗜。三九已至齐板,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間葛菇,已是汗流浹背甘磨。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留熟呛,地道東北人宽档。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像庵朝,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子又厉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理九府,服務(wù)發(fā)現(xiàn),斷路器覆致,智...
    卡卡羅2017閱讀 134,672評(píng)論 18 139
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,152評(píng)論 30 470
  • 最近一朋友正準(zhǔn)備跳槽侄旬,就從各處搜索整理一些基礎(chǔ),便于朋友復(fù)習(xí)煌妈,也便于自己復(fù)習(xí)查看. 1. 回答person的ret...
    smile麗語(yǔ)閱讀 1,742評(píng)論 0 7
  • 1.項(xiàng)目經(jīng)驗(yàn) 2.基礎(chǔ)問(wèn)題 3.指南認(rèn)識(shí) 4.解決思路 ios開(kāi)發(fā)三大塊: 1.Oc基礎(chǔ) 2.CocoaTouch...
    陽(yáng)光的大男孩兒閱讀 4,988評(píng)論 0 13
  • 37.cocoa內(nèi)存管理規(guī)則 1)當(dāng)你使用new儡羔,alloc或copy方法創(chuàng)建一個(gè)對(duì)象時(shí)宣羊,該對(duì)象的保留計(jì)數(shù)器值為1...
    如風(fēng)家的秘密閱讀 848評(píng)論 0 4