简体   繁体   中英

break retain cycle in a block nested in another block

Sometimes I use a block nested in another block, here is my code

- (void)test {
    __weak typeof(self) weakSelf = self;
    [self.viewSource fetchData:^(BOOL succeed, NSError * _Nonnull error, id  _Nonnull data) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf.dataSource disposalData:^{
        // here is the strongSelf ok? do I have to do something to avoid retain cycle?
            [strongSelf updateUI];
        }];
    }];
}
- (void)updateUI {
    
}

I doubt the inner block still has a retain cycle?

    [strongSelf.dataSource disposalData:^{
        [strongSelf updateUI];
    }];

my question is what is the correct way to break the retain cycle in such situation?


here is the additional discussion, as many friend mentioned about this, if I remove __strong typeof(weakSelf) strongSelf = weakSelf; , the inner block has no retain cycle? Is it perfectly correct?

- (void)test {
    __weak typeof(self) weakSelf = self;
    [self.viewSource fetchData:^(BOOL succeed, NSError * _Nonnull error, id  _Nonnull data) {
        [weakSelf.dataSource disposalData:^{
            [weakSelf updateUI];
        }];
    }];
}
- (void)updateUI {
    
} 

I think you can just create new strong reference inside nested block, like this:

- (void)test {
    __weak typeof(self) weakSelf = self;
    [self.viewSource fetchData:^(BOOL succeed, NSError * _Nonnull error, id  _Nonnull data) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf.dataSource disposalData:^{
            __strong typeof(weakSelf) strongSelf = weakSelf; // <- new strong ref
            [strongSelf updateUI];
        }];
    }];
}

It will override the first strongSelf in the nested block scope. And it will be only alive during the execution of the nested block without strong reference cycle created. I think so =)

You don't create a strong reference to a weakSelf. All variables copied in blocks are owned as a strong reference. __weak can be released by self, but it is retained by block. A retain cycle is produced when self which has a strong reference to a block cannot go out of scope because the block holds a strong reference to self.

 __weak typeof(self) weakSelf = self; //This is defined as weak to the instance that creates it.

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
    NSLog(@"%@", weakSelf.description);// Here weak self is strongly referenced by block copy.
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@ second dispatch", weakSelf.description);// Here weak self is also strongly referenced by block.
    });
});

Here self can be deallocated and the block will also be deallocated. This is because the block has a strong pointer to weakSelf, but not a strong pointer to self.

Maybe I should clarify a bit. This block is called in a method. If self is deallocated the method does not exist. There is no need to reference strong self. Even if deallocated after the first block executes, self does not need to call its method updateUI. You would only use strong if another object took ownership of the block and wanted to retain self by the block, which would be owned by the object that has it(thus preventing a memory leak). That would keep self during execution, provided the first allocation was done with the object in scope. ie: Deallocation did not occur before assigning __strong self Additionally, there is no reason to keep an object in memory just to perform UI work. The weak reference should be nilled out as soon as the UI wants to be deallocated.

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