浅谈NSProxy
2022-04-07 本文已影响0人
_涼城
什么是 NSProxy
在苹果官方文档中是这样对 NSProxy 描述的:一个抽象的根类,通常,发送给代理的消息被转发到真实对象,或使代理加载(或转换为)真实对象。头文件代码如下:
@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
是一个实现了 <NSObject>
协议的根类,NSProxy
实现根类所需的基本方法,包括 <NSObject>
协议中定义的方法。然而,作为一个抽象类,它不提供初始化方法,并且在收到任何未响应的消息时引发异常。因此,
- 一个具体的子类必须提供一个初始化或创建方法,
- 并重写
forwardInvocation:
和methodSignatureForSelector:
方法来处理它自己没有实现的消息。-
forwardInvocation
的子类实现:应该执行处理调用所需的任何操作,例如通过网络转发调用或加载真实对象并将调用传递给它。 -
methodSignatureForSelector:
需要提供给定消息的参数类型信息;子类的实现应该能够确定它需要转发的消息的参数类型,并且应该相应地构造一个NSMethodSignature
对象。
-
中介者
使用 NSProxy
对 target
进行消息转发,并不会对 target
造成引用关系。 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
能对多个对象方法进行转发,就使得 NSProxy
具有了多个对象的方法,可以实现“多继承”。