zoukankan      html  css  js  c++  java
  • [iOS]dispatch_after()中self和weakself的使用

    苹果对编译器在不断优化,GCD方法中的block基本都不需要使用weakself,并不会造成循环引用。
    dispatch_after官方文档中对block部分的说明:
    一:使用self
    从ViewControllerA push 到 ViewControllerB。ViewControllerB中代码:
    #import "ViewControllerB.h"
    
    @interface ViewControllerB ()
    
    @end
    
    @implementation ViewControllerB
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        self.view.backgroundColor = [UIColor blueColor];
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self log];
        });
        
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    - (void)log
    {
        NSLog(@"Finish");
    }
    
    - (void)dealloc
    {
        NSLog(@"dealloc");
    }

    输出结果

    pop事件后,ViewControllerB关闭,但并没有立刻调用dealloc方法。而是等待倒计时结束后,log方法执行完成,然后再调用dealloc方法。
    整个过程不会发生循环引用,在dispatch_after时间结束之前,block强持有self,时间结束后,block被释放,随后ViewControllerB被释放。
     
    二:使用weakself
    将代码修改为
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        NSLog(@"pop action");
        
        __weak ViewControllerB *weakself = self;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakself log];
        });
        
        [self.navigationController popViewControllerAnimated:YES];
    }

    输出结果

    在pop之后,立即调用了dealloc方法,ViewControllerB被释放。不会调用log方法。
     
    三:使用weak-strong dance
    将代码修改为
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        NSLog(@"pop action");
        
        __weak ViewControllerB *weakself = self;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            __strong ViewControllerB *strongself = weakself;
            [strongself log];
        });
        
        [self.navigationController popViewControllerAnimated:YES];
    }

    结果与使用weakself相同。

    四:结论

    1:上述代码中,如果去除[self.navigationController popViewControllerAnimated:YES]操作,三种方法都能够正常完成任务。

    2:当block时间内,如果返回上一页面或其他类似操作,导致当前ViewController消失时。

    使用self,ViewController会被block强引用,block时间截止完成回调后,释放block,进而释放ViewController。

    使用weakself时,不存在强引用,ViewController会被直接销毁。

    3:weak-strong dance,在dispatch_after中并没有实际意义。

  • 相关阅读:
    mysql8.0 一次性备份导出/导入恢复所有数据库
    访问服务器共享资源不需要输帐号和密码
    win7 系统 提示用户'sa'登录失败
    Adoquery.disablecontrols和enablecontrols
    DBGridEh 导出数据到EXCEL文件
    Microsoft SQL Server 2005资料库(数据库)卸载方法
    64位操作系统下创建组件失败的解决办法
    U盘中的文件为什么看不见?
    解决错误提示unable to invoke code completion due to errors in source cord.
    浪潮服务器Windows Server系统异常断电导致系统中CentOS7虚拟机系统崩溃无法正常启动grub2故障修复error: relocation 0x48 is not implemented yet
  • 原文地址:https://www.cnblogs.com/EverNight/p/14608096.html
Copyright © 2011-2022 走看看