【问题标题】:Is it correct to use local variable name "self" in blocks?在块中使用局部变量名“self”是否正确?
【发布时间】:2015-05-18 09:58:50
【问题描述】:

我发现构造 __strong typeof(self)self = weakSelf。

它允许删除 NSAssert 宏 self 捕获,但我怀疑以这种方式使用它是否正确?

__weak typeof(self)weakSelf = self;
self.signupBlock = ^{
    __strong typeof(self)self = weakSelf;
    NSLog (@"%d", self.property)
    NSAssert((self.property > 5), @"Some message");
}

请指教。

对不起,我不得不先说使用 __strong typeof(self)strongSelf = weakSelf;

构造结果是警告和我想mem循环,当使用NSAssert宏时,因为它包含self中。

【问题讨论】:

  • self 有什么问题? weakSelf 是干什么用的?
  • 因为 OP 在块中编写代码,限制直接访问其中的 self 对象。
  • 不,一点也不。

标签: ios objective-c-blocks self


【解决方案1】:

self 只是一个变量名,所以在本地重新定义它是完全可以的。它甚至可能比

__strong typeof(weakSelf) strongSelf = weakSelf;

因为

  • 它使代码易于阅读
  • 它可以防止您错误地引用“真实”self 并可能创建保留周期。

此外,您可能希望查看this question 的答案以讨论何时在块中使用弱/强self,并查看libextobjc 库以获取整洁的@weakify / @strongify 宏。

【讨论】:

  • 是的,但是使用 NSAssert 看起来会出现问题。我对本地变量的“自我”命名感兴趣,并且害怕一些问题。现在我对“自我”的本地使用很平静。
【解决方案2】:

将代码更改为,以便清楚您在块中仅引用 strongSelf

__weak typeof(self) weakSelf = self;
self.signupBlock = ^{
    typeof(weakSelf) strongSelf = weakSelf;
    if strongSelf {
        NSLog (@"%d", strongSelf.property)
        NSAssert((strongSelf.property > 5), @"Some message");
    }
}

您的代码与自我__weak typeof(self) weakSelf = self; 建立了弱连接。然后当它需要稍后调用 self 时,它会建立与 self typeof(weakSelf) strongSelf = weakSelf; 的强连接并检查 self 是否仍然存在(尚未释放)if strongSelf {。如果是这样,强连接将在其余代码运行时使其保持活动状态,这在许多情况下可能涉及另一个块来调用主线程(即强连接)。

【讨论】:

  • 通常这样做,但没有检查。很好的练习,谢谢。在主题问题中,变量名 self 很感兴趣。
【解决方案3】:

NSAssert 应该只在 Objective-C 方法中使用,因此它使用 self_cmd。块不是 Objective-C 方法,所以你不应该在其中使用NSAssert。你应该改用NSCAssert

【讨论】:

    【解决方案4】:

    是的,在 ObjC 中使用 self 作为变量名很好。

    我为需要中断由存储块引起的保留周期的情况制作了一个花哨的宏:

    #define StrongSelf  __strong  __typeof__((__typeof__(self))self)
    #define WeakSelf    __weak    __typeof__((__typeof__(self))self)
    
    #define RecoverSelf  for (BOOL _continue_loop = YES; _continue_loop; _continue_loop = NO)              \
                         for (StrongSelf this = self; this != nil && _continue_loop; _continue_loop = NO)  \
                         for (StrongSelf self = this; _continue_loop; _continue_loop = NO)
    #define WeakenSelf   for (BOOL _continue_loop = YES; _continue_loop; _continue_loop = NO) \
                         for (WeakSelf   this = self;  _continue_loop; _continue_loop = NO)   \
                         for (WeakSelf   self = this;  _continue_loop; _continue_loop = NO)
    

    你可以这样使用:

    WeakenSelf {
        _signupBlock = ^{
            RecoverSelf {
                NSLog (@"%d", self.property)
                NSAssert((self.property > 5), @"Some message");
            }
        }
    }
    

    【讨论】:

    • 不明白怎么用,但是看起来不错
    • WeakSelf 块中对self 的每个引用都是弱的(就像你的__weak typeof …)。因此,对self 的弱引用将被传递给阻止保留循环的块。 -- RecoverSelf 做相反的事情,内部对self 的引用再次变得强大。此外,仅当self 仍在内存中且未变为nil 时,才会执行代码。 -- 所以它基本上和你在最初的例子中做的一样,只是语法更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    • 2018-05-21
    相关资源
    最近更新 更多