YYWeakProxy解决NSTimer循环引用问题:
YYWeakProxy *weakProxy = [YYWeakProxy proxyWithTarget:self]; self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:weakProxy selector:@selector(weakProxyTimer) userInfo:nil repeats:YES];
|
原理:
生成一个临时对象,让 displayLink 强引用这个临时对象,在这个临时对象中弱引用 self。
self-强->displayLink-强->YYWeakProxy-弱->self,没有形成循环引用
核心代码:
@property (nonatomic, weak, readonly) id target; + (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)]; }
|
YYWeakProxy:
YYWeakProxy 继承自 NSProxy,NSProxy 是 Foundation 中的一个基类,实现了 NSObject 协议。
NSProxy 做为消息转发的抽象代理类,自身能够处理的方法极少(仅 <NSObject> 接口中定义的部分方法,没有 init 方法,子类必须实现 initWithXXX: forwardInvocation: 和 methodSignatureForSelector: 方法), 专门用于消息转发,相比NSObject类省去了消息查找和动态方法解析流程,直接进行消息转发,所以专门做消息转发的话NSProxy效率更快。
NSProxy:
NSProxy是一个虚类,你可以通过继承它,并重写这两个方法以实现消息转发到另一个实例。
- (void)forwardInvocation:(NSInvocation *)anInvocation; - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;
|
负责将消息转发到真正的target的代理类。
举个例子,你想要卖一件商品,但是你并不想直接跟卖家接触(直接向target发消息),这时你去找了一个第三方,你告诉这个第三方你要买什么、出多少钱买、什么时候要等(向代理发消息),第三方再去跟卖家接触并把这些信息转告卖家(转发消息给真实的target),最后通过第三方去完成这个交易。