iOS循環(huán)引用

一、循環(huán)引用的幾種情況

自循環(huán)引用


image.png
a、b控制器
1.    a強引用b
2.    b有個屬性b1
3.    a.b.b1 = a.b; 
4.    當a釋放時 b無法正常釋放

相互循環(huán)引用


image.png
對象A內(nèi)部強持有obj,對象B內(nèi)部強持有obj,若此時對象A的obj指向?qū)ο驜,同時對象B中的obj指向?qū)ο驛,就是相互引用。
1.self強持有b
2.self.b.delegate = self;
3.b強引用delegate
4.self->b->delegate-->self

多循環(huán)引用


image.png

二、常見循環(huán)引用

1.block

對象強引用block,在block內(nèi)部又引用了該對象或者該對象的屬性就會造成循環(huán)引用

解決方法
1.weak-strong 強弱共舞
單獨使用weak會導(dǎo)致block持有的對象被提前釋放
__strong是為了防止block持有的對象提前釋放
__strong可以保證在block執(zhí)行完后改對象再釋放

__block  當前VC * vc = self ;
self.block = ^{
方法
self = nil ;
}

3.將self作為block的參數(shù)傳入

self.testBlock = ^(UIViewController *vc) {
        //使用vc
    };
    self.testBlock(self);

2.代理

1.self強持有b
2.self.b.delegate = self;
3.b強引用delegate
4.self->b->delegate-->self

解決方法
使用weak修飾delegate

特例CABasicAnimationDelegate使用strong修飾

NStimer

循環(huán)引用 myTimer無法釋放
self強引用myTimer,mytimer的target又是self

  self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(doSomething) userInfo:nil repeats:YES];

- (void)dealloc {
  [self.myTimer invalidate];
  self.myTimer = nil;
}

解決方法
1.在ViewController執(zhí)行dealloc前釋放timer

可以在viewWillAppear中創(chuàng)建timer
可以在viewWillDisappear中銷毀timer

2.封裝FcTimer

.h
@interface FcTimer : NSTimer
//開啟定時器
- (void)startTimer;
//暫停定時器
- (void)stopTimer;
@end

.m
@implementation FcTimer {
    NSTimer *_timer;
}

- (void)stopTimer{
    if (_timer == nil) {
        return;
    }
    [_timer invalidate];
    _timer = nil;
}

- (void)startTimer{
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(work) userInfo:nil repeats:YES];
}

- (void)work{
    NSLog(@"正在計時中。。。。。。");
}

- (void)dealloc{
   NSLog(@"%s",__func__);
    [_timer invalidate];
    _timer = nil;
}
@end

這個方式主要就是讓FcTimer強引用NSTimer,NSTimer強引用FcTimer,避免讓NSTimer強引用ViewController,這樣就不會引起循環(huán)引用,然后在dealloc方法中執(zhí)行NSTimer的銷毀,相對的FcTimer也會進行銷毀了。

3.使用系統(tǒng)提供的帶block的timer方法

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:
(BOOL)repeats block:(void (^)(NSTimer *timer))block 
API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:
(BOOL)repeats block:(void (^)(NSTimer *timer))block 
API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

- (instancetype)initWithFireDate:(NSDate *)date interval:
(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block 
API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

1.避免block的循環(huán)引用,使用__weak和__strong來避免
2.在持用NSTimer對象的類的方法中-(void)dealloc調(diào)用NSTimer 的- (void)invalidate方法;

4.使用基類NSProxy處理

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容