查看了YYWeakProxy的代碼,僅僅是重載了父類的方法,將輸入的target保存為實例變量,然后返回self。在YYKit中的使用地方有:
YYAnimatedImageView中151行
_link = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self] selector:@selector(step:)];
YYWebImageOperation.m的306行
_connection = [[NSURLConnection alloc] initWithRequest:_request delegate:[YYWeakProxy proxyWithTarget:self]];
YYLabel.m的143行:
_longPressTimer = [NSTimer timerWithTimeInterval:kLongPressMinimumDuration
target:[YYWeakProxy proxyWithTarget:self]
selector:@selector(_trackDidLongPress)
userInfo:nil
repeats:NO];
等等。
主要是使用在傳入self時,方法會對self進行強引用。使用YYWeakProxy是為了解決強引用的問題。
強引用引起的問題是,因為一般NSTimer的invalidate方法是放在dealloc方法中去執(zhí)行,而RunLoop已經(jīng)強引用了NSTimer,所以當界面已經(jīng)被摧毀時,而因為self被NSTimer強引用,NSTimer被RunLoop引用,所以不會執(zhí)行dealloc方法。因為不執(zhí)行dealloc方法,導致invalidate不會被執(zhí)行。此時self就會內(nèi)存泄露了。
使用了YYWeakProxy后,當界面被摧毀時,因為NSTimer沒有引用self,而是引用了YYWeakProxy。所以可以執(zhí)行dealloc方法,此時在dealloc中執(zhí)行了invalidate。這樣就會解除NSTimer對YYWeakProxy的強引用。最終self,NSTimer和YYWeakProxy也都得到了釋放,內(nèi)存沒有被泄露。
為何YYWeakProxy能夠實現(xiàn)呢,今天看到了回答的最好的答案:原文章
NSProxy本身是一個抽象類,它遵循NSObject協(xié)議,提供了消息轉發(fā)的通用接口,NSProxy通常用來實現(xiàn)消息轉發(fā)機制和惰性初始化資源。不能直接使用NSProxy。需要創(chuàng)建NSProxy的子類,并實現(xiàn)init以及消息轉發(fā)的相關方法,才可以用。
YYWeakProxy繼承了NSProxy,定義了一個弱引用的target對象,通過重寫消息轉發(fā)等關鍵方法,讓target對象去處理接收到的消息。在整個引用鏈中,Controller對象強引用NSTimer/CADisplayLink對象,NSTimer/CADisplayLink對象強引用YYWeakProxy對象,而YYWeakProxy對象弱引用Controller對象,所以在YYWeakProxy對象的作用下,Controller對象和NSTimer/CADisplayLink對象之間并沒有相互持有,完美解決循環(huán)引用的問題。
// END