1.属性传值循环引用
cell 添加到tableView上被tanleView强引用,cell中tableView被强引用,造成循环引用;
所以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关键字循环引用
class A强引用BView, BView的代理指向A,因为delegate是strong关键字修饰,所以BView会强引用A的实例,造成循环引用
所以delegate关键字应该用weak修饰
定义:
@interface Class A: NSObject
@property (nonatomic, strong) BView *someView;
@property (nonatomic, strong) XXXDelegate delegate;
调用:
self.someView.delegate = self;
3.block捕获变量,循环引用
self持有block,block截获self(这一点我也没搞太明白),赋值会把block copy到堆上,持有相关变量,就是self持有block,block又持有self,形成循环引用
self.block = ^{
self.someProperty = xxx;
}
//解决方式
__weak typeOf(self) weakSelf = self;
self.block = ^{
weakSelf.someProperty = xxx;
}
4.timer循环引用
viewController--->timer--->viewController
造成循环引用,使用weak不能够打破循环引用:由于timer已经加入到runloop中,而且是个重复循环操作,所以这个runloop好像停不下来了。。。所以timer也就无法释放,而他对当前的对象又是强引用。
创建中间层弱引用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
}