iOS NSProxy和NSObject設計代理類差異

轉自:使用NSProxy和NSObject設計代理類的差異

經(jīng)常發(fā)現(xiàn)在一些需要使用消息轉發(fā)而創(chuàng)建代理類時, 不同的程序員都有著不同的使用方法, 有些采用繼承于NSObject, 而有一些采用繼承自NSProxy. 二者都是Foundation框架中的基類, 并且都實現(xiàn)了<NSObject>這個接口, 從命名和文檔中看NSProxy天生就是用來干這個事情的. 但即便如此, 它們卻都定義了相同的消息轉發(fā)的接口, 那我們在使用二者來完成這個工作時有什么差異呢.

先貼一下通過二者來創(chuàng)建代理類的最基本實現(xiàn)代碼.

繼承自NSProxy

#import "XCProxy.h"

@interface XCProxy ()
@property (strong, nonatomic) id target;
@end

@implementation XCProxy

- (id)initWithObject:(id)object {
    self.target = object;
    return self;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}

@end

繼承自NSObject

@interface XCObject ()
@property (strong, nonatomic) id target;
@end

@implementation XCObject

- (id)initWithObject:(id)object {
    self = [super init];
    if (self) {
        self.target = object;
    }
    return self;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [self.target methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    [anInvocation invokeWithTarget:self.target];
}

@end

代碼基本是一致的, 除了初始化時規(guī)范的寫法有細節(jié)差異, 這個差異是因為NSProxy這個基類沒有定義默認的init方法.

1.經(jīng)測試發(fā)現(xiàn)以下兩個在<NSObject>中定義的接口, 在二者之間表現(xiàn)是不一致的:
NSString *test = @"testString";
XCProxy *p = [[XCProxy alloc] initWithObject:test];
XCObject *o = [[XCObject alloc] initWithObject:test];

NSLog(@"proxy length %d", [p respondsToSelector:@selector(length)]);
NSLog(@"object length %d", [o respondsToSelector:@selector(length)]);

NSLog(@"proxy kindOfClass %d", [p isKindOfClass:[NSString class]]);
NSLog(@"object kindOfClass %d", [o isKindOfClass:[NSString class]]);

結果會輸出完成不同的結論:

proxy length 1
object length 0
proxy kindOfClass 1
object kindOfClass 0

也就是說通過繼承自NSObject的代理類是不會自動轉發(fā)respondsToSelector:isKindOfClass:這兩個方法的, 而繼承自NSProxy的代理類卻是可以的. 測試<NSObject>中定義的其它接口二者表現(xiàn)都是一致的.

2.NSObject的所有Category中定義的方法無法在XCObject中完成轉發(fā)莫杈。

舉一個很常見的例子, valueForKey:是定義在NSKeyValueCoding這個NSObject的Category中的方法, 嘗試二者執(zhí)行的表現(xiàn).

NSLog(@"proxy valueForKey %@", [p valueForKey:@"length"]);
NSLog(@"object valueForKey %@", [o valueForKey:@"length"]);

這段代碼第一句能正確運行, 但第二行卻會拋出異常, 分析最終原因其實很簡單, 因為valueForKey:是NSObject的Category中定義的方法, 讓NSObject具備了這樣的接口, 而消息轉發(fā)是只有當接收者無法處理時才會通過forwardInvocation:來尋求能夠處理的對象术羔。

3.結論: 如此看來NSProxy確實更適合實現(xiàn)做為消息轉發(fā)的代理類, 因為作為一個抽象類, NSProxy自身能夠處理的方法極小(僅<NSObject>接口中定義的部分方法), 所以其它方法都能夠按照設計的預期被轉發(fā)到被代理的對象中。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汗贫,一起剝皮案震驚了整個濱河市伴郁,隨后出現(xiàn)的幾起案子耿战,更是在濱河造成了極大的恐慌,老刑警劉巖焊傅,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剂陡,死亡現(xiàn)場離奇詭異狈涮,居然都是意外死亡,警方通過查閱死者的電腦和手機鸭栖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門歌馍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人晕鹊,你說我怎么就攤上這事松却。” “怎么了溅话?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵晓锻,是天一觀的道長。 經(jīng)常有香客問我飞几,道長砚哆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任屑墨,我火速辦了婚禮躁锁,結果婚禮上,老公的妹妹穿的比我還像新娘卵史。我一直安慰自己战转,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布以躯。 她就那樣靜靜地躺著槐秧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪寸潦。 梳的紋絲不亂的頭發(fā)上色鸳,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音见转,去河邊找鬼命雀。 笑死,一個胖子當著我的面吹牛斩箫,可吹牛的內(nèi)容都是我干的吏砂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乘客,長吁一口氣:“原來是場噩夢啊……” “哼狐血!你這毒婦竟也來了?” 一聲冷哼從身側響起易核,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤匈织,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缀匕,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡纳决,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了乡小。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阔加。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖满钟,靈堂內(nèi)的尸體忽然破棺而出胜榔,到底是詐尸還是另有隱情,我是刑警寧澤湃番,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布夭织,位于F島的核電站,受9級特大地震影響吠撮,放射性物質(zhì)發(fā)生泄漏摔癣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一纬向、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧戴卜,春花似錦逾条、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至江锨,卻和暖如春吃警,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背啄育。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工酌心, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挑豌。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓安券,卻偏偏與公主長得像,于是被迫代替她去往敵國和親氓英。 傳聞我的和親對象是個殘疾皇子侯勉,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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

  • 前言:面試筆試都是必考語法知識點。請認真復習和深入研究OC铝阐。 目錄:iOS-面試題-OC基礎篇 (1) - (84...
    麥穗0615閱讀 4,260評論 0 33
  • 1.設計模式是什么址貌? 你知道哪些設計模式,并簡要敘述? 設計模式是一種編碼經(jīng)驗练对,就是用比較成熟的邏輯去處理某一種類...
    司馬DE晴空閱讀 1,295評論 0 7
  • 簡介 Runtime 又叫運行時遍蟋,是一套底層的 C 語言 API,其為 iOS 內(nèi)部的核心之一锹淌,我們平時編寫的 O...
    專業(yè)男神經(jīng)閱讀 906評論 0 2
  • ??最近看了『神奇的 BlocksKit』系列匿值,里面說到動態(tài)代理是BlocksKit的精華部分,對于使用block...
    foreverSun_122閱讀 1,152評論 1 7
  • 在清明這個節(jié)日上赂摆,我們都不會說清明節(jié)快樂挟憔,因為都知道這不是我們的節(jié)日,是哪些逝去的人的節(jié)日烟号。 死亡是一件恐怖的事绊谭,...
    op牽絆閱讀 156評論 0 1