美文网首页
iOS dispatch_after延迟执行导致延迟deallo

iOS dispatch_after延迟执行导致延迟deallo

作者: _清墨 | 来源:发表于2021-04-12 15:48 被阅读0次

    我们新建一个NewViewController,在开始的ViewController写如下代码

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(100, 100, 100, 50);
        btn.backgroundColor = [UIColor brownColor];
        [btn addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
        
    }
    
    -(void)jump{
        NewViewController *newVC = [[NewViewController alloc]init];
        [self presentViewController:newVC animated:YES completion:nil];
    }
    

    然后在NewViewController里:

    -(void)dealloc{
        NSLog(@"--------------dealloc");
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(100, 300, 100, 50);
        btn.backgroundColor = [UIColor brownColor];
        [btn addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
        
        __weak typeof(self) weakSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self log];
            NSLog(@"--------------after");
        });
        
    }
    
    -(void)log{
        NSLog(@"--------------log");
    }
    
    -(void)jump{
        NSLog(@"--------------dismiss");
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    

    运行之后,我们一跳进newVC里面返回,这时候:

    image.png
    结果说明我们dismiss的时候,newVC还没有被释放,dealloc方法在dispatch_after延迟方法执行之后才会走,原因就是dispatch_after强引用了self(即newVC),等强引用过去,self才能得到释放走dealloc

    接下来,我们在dispatch_after里把 self 用 __weak修饰,block里把self改为weakself,我们还是一样的操作流程,看看结果:

    - (void)viewDidLoad {
        [super viewDidLoad];
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(100, 300, 100, 50);
        btn.backgroundColor = [UIColor brownColor];
        [btn addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
        
        __weak typeof(self) weakSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakSelf log];
            NSLog(@"--------------after");
        });
        
    }
    
    image.png
    当我们用weak修饰self时,dispatch_after并没有强引用self,所以我们dissmiss时,dealloc立马就会走,然后10s后,dispatch_after的执行函数还是会执行,输出了after,但是没有输出log,这是因为用的weakSelfdissmiss后,newVC已经被释放,这时候代码 [weakSelf log];等同于[nil log];,所以才不会输出log。

    使用注意

    虽然dispatch_after里直接调用self不会造成循环引用,但当我们dispatch_after延迟时间过长的时候,需要考虑是否要及时释放当前对象,如果需要,尽量使用weakSelf这种方式,如果真有需要用到self完成一些操作再释放的需求,可以按需编写代码。

    相关文章

      网友评论

          本文标题:iOS dispatch_after延迟执行导致延迟deallo

          本文链接:https://www.haomeiwen.com/subject/yjsxlltx.html