什么是 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ā)異常勘畔。因此所灸,
- 一個具體的子類必須提供一個初始化或創(chuàng)建方法,
- 并重寫
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
對象知纷。
-
中介者
????使用 NSProxy
對 target
進行消息轉(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)“多繼承”。