一啊犬、NSProxy 簡(jiǎn)介
NSProxy 是一個(gè)抽象類(lèi),它實(shí)現(xiàn)了protocol NSObject 所要求的基本方法嫉入,譬如內(nèi)省相關(guān)的isKindOfClass:派發(fā)消息相關(guān)的performSelector 系列相關(guān)方法等焰盗;但是不能直接使用它創(chuàng)建對(duì)象。
子類(lèi)化NSProxy 的要求也很簡(jiǎn)單咒林,實(shí)現(xiàn)-forwardInvocation: 和-methodSignatureForSelector: 這兩個(gè)方法即可姨谷,顯然,這兩個(gè)方法與消息轉(zhuǎn)發(fā)相關(guān)映九,實(shí)現(xiàn)這兩個(gè)方法的典型姿勢(shì)是:
- (void)forwardInvocation:(NSInvocation *)anInvocation {
[anInvocation invokeWithTarget:_realObject]; // _realObject是自定義的實(shí)例變量
}
– (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [_realObject methodSignatureForSelector:aSelector];
}
二、NSProxy 的消息轉(zhuǎn)發(fā)機(jī)制
雖然NSProxy 和 class NSObject 都定義了 -forwardInvocation: 和 -methodSignatureForSelector, 但這兩個(gè)方法并沒(méi)有在protocol NSObject 中聲明瞎颗;兩者對(duì)這兩個(gè)方法的調(diào)用邏輯完全不同件甥。
對(duì)于Class NSObject 而言捌议,接收到消息后先去自身的方法列表里找匹配的 selector,如果找不到引有,會(huì)沿著繼承體系去 superclass 的方法列表找瓣颅;如果還找不到,先后會(huì)經(jīng)過(guò)+resolveInstanceMethod:和-forwardingTargetForSelector:處理譬正,處理失敗后宫补,才會(huì)到-methodSignatureForSelector:/-forwardInvocation:進(jìn)行最后的掙扎。
但對(duì)于NSProxy曾我,接收 unknown selector 后粉怕,直接回調(diào)-methodSignatureForSelector:/-forwardInvocation:,消息轉(zhuǎn)發(fā)過(guò)程比class NSObject要簡(jiǎn)單得多抒巢。
三贫贝、-init
除了上述的-methodSignatureForSelector:和-forwardInvocation:,NSProxy另外兩個(gè)方法也非常值得說(shuō)一說(shuō)蛉谜。
首先是-init稚晚。事實(shí)上,NSProxy沒(méi)有定義這個(gè)方法型诚,對(duì)于直接繼承NSProxy的類(lèi)客燕,創(chuàng)建對(duì)象時(shí)不需要使用[super init]之類(lèi)的調(diào)用進(jìn)行初始化。為啥 Apple 不為NSProxy提供默認(rèn)的構(gòu)造器呢狰贯?我想這和它的定位有關(guān)吧也搓,它是一個(gè)抽象類(lèi),不提供默認(rèn)的-init反而能進(jìn)一步阻止用戶直接使用NSProxy創(chuàng)建對(duì)象暮现。
四还绘、NSProxy 優(yōu)勢(shì)
用NSProxy設(shè)計(jì)代理類(lèi)的優(yōu)勢(shì)
NSProxy會(huì)將自省相關(guān)方法直接 forward 到forwardInvocation:回調(diào),如果基于class NSObject實(shí)現(xiàn)類(lèi)似的效果栖袋,得另外寫(xiě)不少代碼拍顷,比較麻煩。
NSProxy比class NSObject干凈得多塘幅,后者各種 category(譬如NSObject(NSKeyValueCoding))定義了諸多方法昔案,這些方法的存在使得消息轉(zhuǎn)發(fā)變得更麻煩,因?yàn)榈脜^(qū)分class NSObject對(duì)象本身和其所指向的 realObject电媳。