您当前的位置: 首页 >  ios

培根芝士

暂无认证

  • 0浏览

    0关注

    446博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

iOS常见的不调用dealloc的原因

培根芝士 发布时间:2019-01-21 11:29:44 ,浏览量:0

(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;

 

关注
打赏
1660824269
查看更多评论
立即登录/注册

微信扫码登录

0.0440s