Duck
Duck

Reputation: 35933

Block retaining self for CGFloat ivars?

I have a class with an ivar like this:

@interface MCProgressBarView() {
  CGFloat minimumForegroundWidth;
  CGFloat availableWidth;
}

later in code, I have this:

dispatch_async(dispatch_get_main_queue(), ^{

    CGRect frame = _foregroundImageView.frame;
    frame.size.width = roundf(minimumForegroundWidth + availableWidth * valor);
    _foregroundImageView.frame = frame;

    [self layoutIfNeeded];

});

The minimumForegroundWidth line of this later code shows this error:

Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior

I know how to solve this for properties but what about CGFloat ivars?

Upvotes: 2

Views: 60

Answers (2)

Rob
Rob

Reputation: 437381

I know how to solve this for properties but what about CGFloat ivars

As you know, the solution for properties is weakSelf pattern:

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    CGFloat localVar = weakSelf.property;
    ...
});

The solution for ivars is very similar except you need to explicitly check to see if weakSelf is nil or not, because you cannot dereference an ivar from nil pointer. So you create a strong local reference to your weakSelf and then check to see if it’s not nil:

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
        CGFloat localVar = strongSelf->ivar;
    }
});

Obviously, in your example, we generally wouldn’t worry about strong reference cycles (because the cycle is resolved as soon as the block finishes) and just use self->minimumForegroundWidth syntax to silence the warning. But the above weakSelf patterns are important where strong reference cycles are possible (e.g., you’re saving the block in a property, using it for repeating timer, etc.).

Upvotes: 2

Rob Napier
Rob Napier

Reputation: 299265

The syntax is self->minimumForegroundWidth. Arrow rather than dot. It's going back to the fact that self is actually a pointer to struct, and -> is the the C notation for referencing members of that.

Upvotes: 3

Related Questions