iOS中的循環(huán)引用種類

1.屬性傳值循環(huán)引用

cell 添加到tableView上被tanleView強(qiáng)引用,cell中tableView被強(qiáng)引用,造成循環(huán)引用;

所以cell中tableView應(yīng)該用weak關(guān)鍵字

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  TabelViewCell *cell = ...
  cell.tableView = tableView;
  return cell;
}

@interface TableViewCell: UITableViewCell
 @property (nonatomic, strong) UITableView *tableView;
@end

2.delegate屬性用strong關(guān)鍵字循環(huán)引用

class A強(qiáng)引用BView, BView的代理指向A,因?yàn)閐elegate是strong關(guān)鍵字修飾,所以BView會強(qiáng)引用A的實(shí)例,造成循環(huán)引用

所以delegate關(guān)鍵字應(yīng)該用weak修飾

定義:
@interface Class A: NSObject
@property (nonatomic, strong) BView *someView;
@property (nonatomic, strong) XXXDelegate delegate;

調(diào)用:
self.someView.delegate = self;

3.block捕獲變量,循環(huán)引用

self持有block,block截獲self(這一點(diǎn)我也沒搞太明白),賦值會把block copy到堆上,持有相關(guān)變量,就是self持有block,block又持有self,形成循環(huán)引用

 self.block = ^{
      self.someProperty = xxx;
 } 

//解決方式
__weak typeOf(self) weakSelf = self;
self.block = ^{
    weakSelf.someProperty = xxx;
}

4.timer循環(huán)引用

viewController--->timer--->viewController
造成循環(huán)引用,使用weak不能夠打破循環(huán)引用:由于timer已經(jīng)加入到runloop中,而且是個(gè)重復(fù)循環(huán)操作,所以這個(gè)runloop好像停不下來了。。。所以timer也就無法釋放,而他對當(dāng)前的對象又是強(qiáng)引用。

創(chuàng)建中間層弱引用timer,在deinit銷毀timer

class TimerProxy{

    private weak var target:AnyObject?//一定要是弱引用

    private var selector:Selector?

    init(with target:AnyObject, selector:Selector) {
        self.target = target
        self.selector = selector
    }

    @objc public func executeSelector(){
        if (target != nil) && (selector != nil) {
            target?.perform(selector, with: nil)
        }
    }
    deinit {
        debugPrint("TimerProxy已釋放")
    }
}

使用方法:

 let proxy = TimerProxy.init(with: self, selector: #selector(timerDo))
    timer = Timer.init(timeInterval: 1, target: proxy, selector: #selector(proxy.executeSelector), userInfo: nil, repeats: true)
    RunLoop.current.add(timer!, forMode: .common)

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

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