淺談NSProxy

什么是 NSProxy

????在蘋果官方文檔中是這樣對 NSProxy 描述的:一個抽象的根類,通常今膊,發(fā)送給代理的消息被轉(zhuǎn)發(fā)到真實對象咙边,或使代理加載(或轉(zhuǎn)換為)真實對象。頭文件代碼如下:

@interface NSProxy <NSObject> {
    __ptrauth_objc_isa_pointer Class isa;
}

+ (id)alloc;
+ (id)allocWithZone:(nullable NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+ (Class)class;

- (void)forwardInvocation:(NSInvocation *)invocation;
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available");
- (void)dealloc;
- (void)finalize;
@property (readonly, copy) NSString *description;
@property (readonly, copy) NSString *debugDescription;
+ (BOOL)respondsToSelector:(SEL)aSelector;

- (BOOL)allowsWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos);
- (BOOL)retainWeakReference API_UNAVAILABLE(macos, ios, watchos, tvos);

// - (id)forwardingTargetForSelector:(SEL)aSelector;

@end

NSProxy 使用

????可以看到 NSProxy 是一個實現(xiàn)了 <NSObject> 協(xié)議的根類拗胜,NSProxy 實現(xiàn)根類所需的基本方法,包括 <NSObject> 協(xié)議中定義的方法怒允。然而埂软,作為一個抽象類,它不提供初始化方法纫事,并且在收到任何未響應(yīng)的消息時引發(fā)異常勘畔。因此所灸,

  1. 一個具體的子類必須提供一個初始化或創(chuàng)建方法,
  2. 并重寫 forwardInvocation:methodSignatureForSelector: 方法來處理它自己沒有實現(xiàn)的消息炫七。
    • forwardInvocation 的子類實現(xiàn):應(yīng)該執(zhí)行處理調(diào)用所需的任何操作爬立,例如通過網(wǎng)絡(luò)轉(zhuǎn)發(fā)調(diào)用或加載真實對象并將調(diào)用傳遞給它。
    • methodSignatureForSelector: 需要提供給定消息的參數(shù)類型信息诉字;子類的實現(xiàn)應(yīng)該能夠確定它需要轉(zhuǎn)發(fā)的消息的參數(shù)類型懦尝,并且應(yīng)該相應(yīng)地構(gòu)造一個 NSMethodSignature 對象知纷。

中介者

????使用 NSProxytarget 進行消息轉(zhuǎn)發(fā)壤圃,并不會對 target 造成引用關(guān)系。 A ->NSProxy -> B 琅轧。例如伍绳,YYKit/YYWeakProxy,源碼如下:

  • YYWeakProxy.h

    
    /**
     A proxy used to hold a weak object.
     It can be used to avoid retain cycles, such as the target in NSTimer or CADisplayLink.
     
     sample code:
     
         @implementation MyView {
            NSTimer *_timer;
         }
         
         - (void)initTimer {
            YYWeakProxy *proxy = [YYWeakProxy proxyWithTarget:self];
            _timer = [NSTimer timerWithTimeInterval:0.1 target:proxy selector:@selector(tick:) userInfo:nil repeats:YES];
         }
         
         - (void)tick:(NSTimer *)timer {...}
         @end
     */
    @interface YYWeakProxy : NSProxy
    
    /**
     The proxy target.
     */
    @property (nullable, nonatomic, weak, readonly) id target;
    - (instancetype)initWithTarget:(id)target;
    + (instancetype)proxyWithTarget:(id)target;
    
    @end
    
  • YYWeakProxy.m

    #import "YYWeakProxy.h"
    
    
    @implementation YYWeakProxy
    
    - (instancetype)initWithTarget:(id)target {
        _target = target;
        return self;
    }
    
    + (instancetype)proxyWithTarget:(id)target {
        return [[YYWeakProxy alloc] initWithTarget:target];
    }
    
    - (id)forwardingTargetForSelector:(SEL)selector {
        return _target;
    }
    
    - (void)forwardInvocation:(NSInvocation *)invocation {
        void *null = NULL;
        [invocation setReturnValue:&null];
    }
    
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
        return [NSObject instanceMethodSignatureForSelector:@selector(init)];
    }
    
    - (BOOL)respondsToSelector:(SEL)aSelector {
        return [_target respondsToSelector:aSelector];
    }
    
    - (BOOL)isEqual:(id)object {
        return [_target isEqual:object];
    }
    
    - (NSUInteger)hash {
        return [_target hash];
    }
    
    - (Class)superclass {
        return [_target superclass];
    }
    
    - (Class)class {
        return [_target class];
    }
    
    - (BOOL)isKindOfClass:(Class)aClass {
        return [_target isKindOfClass:aClass];
    }
    
    - (BOOL)isMemberOfClass:(Class)aClass {
        return [_target isMemberOfClass:aClass];
    }
    
    - (BOOL)conformsToProtocol:(Protocol *)aProtocol {
        return [_target conformsToProtocol:aProtocol];
    }
    
    - (BOOL)isProxy {
        return YES;
    }
    
    - (NSString *)description {
        return [_target description];
    }
    
    - (NSString *)debugDescription {
        return [_target debugDescription];
    }
    
    @end
    

多繼承

????NSProxy 能對多個對象方法進行轉(zhuǎn)發(fā)乍桂,就使得 NSProxy 具有了多個對象的方法冲杀,可以實現(xiàn)“多繼承”。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睹酌,一起剝皮案震驚了整個濱河市权谁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌憋沿,老刑警劉巖旺芽,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辐啄,居然都是意外死亡采章,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門壶辜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悯舟,“玉大人,你說我怎么就攤上這事砸民〉衷酰” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵岭参,是天一觀的道長反惕。 經(jīng)常有香客問我,道長冗荸,這世上最難降的妖魔是什么承璃? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蚌本,結(jié)果婚禮上盔粹,老公的妹妹穿的比我還像新娘隘梨。我一直安慰自己,他們只是感情好舷嗡,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布轴猎。 她就那樣靜靜地躺著,像睡著了一般进萄。 火紅的嫁衣襯著肌膚如雪捻脖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天中鼠,我揣著相機與錄音可婶,去河邊找鬼。 笑死援雇,一個胖子當(dāng)著我的面吹牛矛渴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惫搏,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼具温,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了筐赔?” 一聲冷哼從身側(cè)響起铣猩,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茴丰,沒想到半個月后达皿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡较沪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年鳞绕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尸曼。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡们何,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出控轿,到底是詐尸還是另有隱情冤竹,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布茬射,位于F島的核電站鹦蠕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏在抛。R本人自食惡果不足惜钟病,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肠阱,春花似錦票唆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至噪伊,卻和暖如春簿煌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鉴吹。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工姨伟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拙寡。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓授滓,卻偏偏與公主長得像琳水,于是被迫代替她去往敵國和親肆糕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

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

  • 1.為什么要弱引用NSTimer2.如何弱引用https://blog.csdn.net/yohunl/artic...
    KevinChein閱讀 422評論 0 0
  • 最佳方案一:使用新API 如果你的系統(tǒng)只支持iOS10以上在孝,強烈建議使用新API诚啃。 這新的API,增加了block...
    片片碎閱讀 2,009評論 0 11
  • NSTimer 是系統(tǒng)提供的定時器私沮,系統(tǒng)提供的api也比較簡單始赎,使用很方便,項目開發(fā)中會經(jīng)常用到仔燕。然而造垛,在使用NS...
    戀空K閱讀 3,958評論 0 13
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,334評論 8 265
  • 前言 NSProxy是iOS開發(fā)中一個消息轉(zhuǎn)發(fā)的基類,它不繼承自NSObject晰搀。因為這個類不太常用五辽,所以對于很多...
    橙娃閱讀 1,855評論 0 2