【问题标题】:Block retaining self for CGFloat ivars?阻止为 CGFloat ivars 保留自我?
【发布时间】:2019-05-31 20:37:04
【问题描述】:

我有一个像这样的 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 隐式保留'self';明确提及“自我”以表示 这是预期的行为

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

【问题讨论】:

    标签: objective-c objective-c-blocks ivar


    【解决方案1】:

    语法是self->minimumForegroundWidth。箭头而不是点。这又回到了这样一个事实,self 实际上是一个指向结构的指针,而-> 是用于引用其成员的 C 表示法。

    【讨论】:

    • 这很奇怪,因为它是一个 C 符号,但它可以工作。谢谢。
    • Objective-C 只是 C…:D(嗯,直到 ObjC2 和 ARC,但它仍然大部分 C.)
    【解决方案2】:

    我知道如何为属性解决这个问题,但是 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 模式在可能存在强引用循环的情况下很重要(例如,您将块保存在属性中,将其用于重复计时器等)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 2020-07-04
      • 2013-12-14
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      相关资源
      最近更新 更多