[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中并没有实际意义。

posted @   EverNight  阅读(1124)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示