0
votes

I am reading the book, it says: To break the strong reference cycle, you declare a __weak pointer outside the block that points to self. Then you can use this pointer inside the block instead of self:

__weak BNREmployee *weakSelf = self; // a weak reference
myBlock = ^{
    NSLog(@"Employee: %@", weakSelf);
};

The block’s reference to the BNREmployee instance is now a weak one, and the strong reference cycle is broken. However, because the reference is weak, the object that self points to could be deallocated while the block is executing. You can eliminate this risk by creating a strong local reference to self inside the block:

__weak BNREmployee *weakSelf = self; // a weak reference
myBlock = ^{
    BNREmployee *innerSelf = weakSelf; // a block-local strong reference
    NSLog(@"Employee: %@", innerSelf);
};

Why I cannot simply do the following?

myBlock = ^{
    BNREmployee *innerSelf = self; // a block-local strong reference
    NSLog(@"Employee: %@", innerSelf);
};

or

BNREmployee *strongSelf = self; 
myBlock = ^{
    BNREmployee *innerSelf = strongSelf; // a block-local strong reference
    NSLog(@"Employee: %@", innerSelf);
};
1
In the last two variants the block captures a strong variable which means you get a reference cycle. The block must capture a weak variable to avoid the cycle. And very, very much should assign it to a strong variable for consistent behaviour (the strong variable may be nil if the weak variable was nil when it was assigned, but the strong variable will not change to the end of the block).gnasher729
@gnasher729 thanks, what do you mean by the strong variable will not change to the end of the block? Could you explain that a bit more?Huibin Zhang

1 Answers

5
votes

Your replacement block directly references self, so ARC will retain self as long as the block exists. If the block is retained by a property of the same object, you have a retain loop.