1.屬性傳值循環(huán)引用
cell 添加到tableView上被tanleView強引用,cell中tableView被強引用异赫,造成循環(huán)引用;
所以cell中tableView應該用weak關鍵字
- (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關鍵字循環(huán)引用
class A強引用BView, BView的代理指向A,因為delegate是strong關鍵字修飾,所以BView會強引用A的實例威蕉,造成循環(huán)引用
所以delegate關鍵字應該用weak修飾
定義:
@interface Class A: NSObject
@property (nonatomic, strong) BView *someView;
@property (nonatomic, strong) XXXDelegate delegate;
調用:
self.someView.delegate = self;
3.block捕獲變量橄仍,循環(huán)引用
self持有block,block截獲self(這一點我也沒搞太明白),賦值會把block copy到堆上娩贷,持有相關變量,就是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中窄陡,而且是個重復循環(huán)操作涂圆,所以這個runloop好像停不下來了。踩衩。。所以timer也就無法釋放萌朱,而他對當前的對象又是強引用。
創(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
}