(1)NSTimer
如果代码中存在NSTimer,当调用以下代码的时候,会增加ViewController的引用计数,需要在关闭页面的时候调用[timer invalidate] 销毁计时器,如果把[timer invalidate]放在了dealloc里,则永远不会被调用。
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime:)
userInfo:nil
repeats:YES];
(2)Block
Block体内使用实例变量也会造成循环引用(retain cycle)—— Block 会 retain ‘self’,而 ‘self’ 又 retain 了 Block,使得拥有这个实例的对象不能释放。 例如当前类有个属性是NSString *name; 如果在block体中使用了self.name,那样这个类就没法释放了。
要解决这个问题只需要在block之前做以下声明,然后在block体内用weakself代替self。
__weak typeof(self) weakself = self;
topView.OnNoticeSelect = ^{
[weakself OnNoticeClick];
};
当 block 本身不被 self 持有,而被别的对象持有,同时不产生循环引用的时候,就不需要使用 weakself 了。
举个例子:
@interface TestViewModel : NSObject
@property (nonatomic, strong) void(^OnTestBlock2)(void);
- (void)OnTestBlock1:(void(^)(void))block;
@end
在另外一个类中引用下面方法的时候会提示循环引用的警告:Capturing 'self' strongly in this block is likely to lead to a retain cycle
self.viewModel = [[TestViewModel alloc] init];
[self.viewModel setOnTestBlock2:^{
[self OnTest];
}];
而引用下面的方法则不会提示循环引用的警告,这个类也能正常的释放。
self.viewModel = [[TestViewModel alloc] init];
[self.viewModel OnTestBlock1:^{
[self OnTest];
}];
常见的UIView动画,NSDictionary和NSArray的枚举器(enumerate),GDC,AFNetworking,Masonry等中的block不会发生循环引用,所以无需使用weakself。
以下用法不会引起循环引用:
[self.models enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self OnTest:obj];
}];
[UIView animateWithDuration:0.1 animations:^{
[self OnTest];
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self OnTest2];
});
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
[session GET:url parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self OnAFSuccess];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[self OnAFFailure];
}];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
if (@available(ios 11.0,*)) make.edges.mas_equalTo(self.view.safeAreaInsets);
else make.edges.mas_equalTo(self.view);
}];
(3)Delegate
在声明delegate的时候需要设置成weak,如果是strong强引用,就不会调用dealloc。
@property (nonatomic,weak)id refreshDelegate;