Если блок находится во владении класса (retained). Например объект хранит свойство - блок.
Объект который владеет блоком - в этом случае и происходит захват self
- внутри блока и происходит retain cycle (цикла владения)
.
Where you get into trouble is something like:
//In the interface:
@property (strong) void(^myBlock)(id obj, NSUInteger idx, BOOL *stop);
//In the implementation:
[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self doSomethingWithObj:obj];
}];
The block retains self, but self doesn't retain the block. If one or the other is released, no cycle is created and everything gets deallocated as it should.
```objc
__weak MyObject *weakSelf = self;
[[SomeOtherObject alloc] initWithCompletion:^{
MyObject *strongSelf = weakSelf;
[strongSelf doSomething];
}];
__weak typeof(self) weakSelf = self;
В инструментах
можно отследить - Record reference counts
retain cycle - strong reference cycle.
The correct solution is this:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
Self-объект хранит (владеет) блок. Блок удерживает self объект.
You don’t need to make two sets of weak references. What you want to avoid with blocks is a retain cycle—two objects keeping each other alive unnecessarily. If I have an object with this property:
@property (strong) void(^completionBlock)(void);
and I have this method:
- (void)doSomething
{
self.completionBlock = ^{
[self cleanUp];
};
[self doLongRunningTask];
}
the block will be kept alive when I store it in the completionBlock
property.
But since it references self
inside the block, the block will keep self alive until
it goes away—but this won’t happen since they’re both referencing each other.