简体   繁体   中英

Do I need a strongSelf in block to keep self alive and does the strongSelf really work?

This is what I have learned: when using self retained block

  1. I need a weakSelf to break retain cycle
  2. I need a strongSelf to prevent self from becoming nil half-way

so I want to test if a strongSelf can really keep self alive like so:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"viewDidLoad");
    self.test = @"test";
    NSLog(@"%@",self.test);
    __weak typeof(self)weakSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        __strong typeof(weakSelf)strongSelf = weakSelf;
        strongSelf.test = @"newTest";
        NSLog(@"%@",strongSelf.test);
    });
}

- (void)dealloc {
    NSLog(@"dealloc");
}

@end

The ViewController will be pushed into a navigationController and pop out immediately. The output is

样品

why the null?

There is another question I have a project which contains tons of weakSelf without strongSelf in the block and I get plenty of signal 11 crash. Is it related? Is it worth to add strongSelf to each of them?

strongSelf ensures that if self was not released yet, it won't during the execution of the block.

If the self is gone before you create strongSelf , it will be nil.

You should check, if strongSelf does contain something:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    typeof(weakSelf)strongSelf = weakSelf; // __strong is not needed
    if(strongSelf){
        strongSelf.test = @"newTest";
        NSLog(@"%@",strongSelf.test);
    }
});

The code in your block is executed after 3s delay. So by this time the weakSelf is already nil. That's why strongSelf is nil

I think you don't hit the problem right. Using weakself will break the retain cycle, however this line:

__strong typeof(weakSelf)strongSelf = weakSelf;

Does not capture strong reference to self until block is executed. Hence if your pointer to VC outside of block is nil, VC will be released and weakSelf will be nil when you hit the block - meaning your strongSelf will be nil also. Capturing strong reference guarantee only that if you have weak self at the begin of the block, you will have it until the end and it won't be dealloc meanwhile. However if weakSelf is nil at begin of the block - strongSelf will be nil also. Moreover you do not need to declare it as strong inside block, as it will be strong by definition, hence it could be replaced by:

typeof(weakSelf)strongSelf = weakSelf;

or

id strongSelf = weakSelf;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM