NSProxy和NSObject一样,也是一个基类,是一个实现协议的基类。
@class NSMethodSignature, NSInvocation;
NS_ASSUME_NONNULL_BEGIN
NS_ROOT_CLASS
@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的类HHProxy,并在里面实现以下方法:
@interface HHProxy : NSProxy
+(instancetype)proxyWithTarget:(id)target;
@property(nonatomic,weak)id target;
@end
@implementation HHProxy
+(instancetype)proxyWithTarget:(id)target{
HHProxy *proxy = [HHProxy alloc];
proxy.target = target;
return proxy;
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
return [self.target methodSignatureForSelector:sel];
}
-(void)forwardInvocation:(NSInvocation *)invocation{
[invocation invokeWithTarget:self.target];
}
注意:上述代码中target用weak修饰,这样才可以避免循环引用。
timer通过HHProxy调用:
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[HHProxy proxyWithTarget:self] selector:@selector(eat) userInfo:nil repeats:YES];
这样就可以避免循环引用了。且NSProxy的效率最高,为什么这么说呢:
通常我们一般的方法调用都是通过objc_msgSend来进行的,然后经过消息发送、动态方法解析、消息转发这三个步骤,而通过代码进行测试,发现继承NSProxy的类,直接执行了methodSignatureForSelector方法,这样就直接进入了消息转发阶段,前两个阶段都省去了,所以效率更高。