[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中並沒有實際意義。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM