Skip to content

Instantly share code, notes, and snippets.

@arturlector
Created March 13, 2016 21:11
Show Gist options
  • Save arturlector/67a2e19c09f3c26eb926 to your computer and use it in GitHub Desktop.
Save arturlector/67a2e19c09f3c26eb926 to your computer and use it in GitHub Desktop.
Как использовать self внутри блоков? Пример retain cycle в блоке?

Как использовать self внутри блоков?

Когда нужен weak refence для self внутри блока?

Если блок находится во владении класса (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];
    }
});

Пример retain cycle в блоке?

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment