阻止 CGFloat ivars 保留自我?

Block retaining self for CGFloat ivars?

我有一个 class 和这样的 ivar:

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

稍后在代码中,我有这个:

dispatch_async(dispatch_get_main_queue(), ^{

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

    [self layoutIfNeeded];

});

后面代码的 minimumForegroundWidth 行显示此错误:

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

我知道如何为属性解决这个问题,但是 CGFloat ivars 呢?

语法为self->minimumForegroundWidth。箭头而不是点。这要追溯到 self 实际上是一个指向结构的指针,而 -> 是引用结构成员的 C 表示法。

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

如您所知,属性的解决方案是 weakSelf 模式:

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

ivars 的解决方案非常相似,只是您需要明确检查 weakSelf 是否为 nil,因为您无法从 nil 指针中取消引用 ivar。因此,您创建了对 weakSelf 的强本地引用,然后检查它是否不是 nil:

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

显然,在您的示例中,我们通常不会担心强引用循环(因为循环会在块完成后立即解决),只需使用 self->minimumForegroundWidth 语法来消除警告。但是上面的 weakSelf 模式在可能存在强引用循环的情况下很重要(例如,您将块保存在 属性 中,将其用于重复计时器等)。