如何使布尔值既静态又 __block?在 iOS?

How to make a boolean both static and __block? in iOS?

bool _hintExist;
- (void)showNotReachable
{
    if (_hintExist) {
        return;
    }

    NSLog(@"Show a hint");

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        _hintExist = NO;
    });
}

上面的代码没问题。有一个按钮可以触发该方法。实际上,我不需要 _hintExist 是一个全局变量。当我试图在 bool _hintExist 前面添加静态和 __block 时,我想在 method.However 中创建 bool _hintExist。会有编译错误。如果我将它设为全局变量,我可以在块中更改 _hintExist,这让我感到很惊讶。有人可以解释为什么吗?如果我在代码中的全局变量 bool _notReachableHintExist 之前添加 static 有什么区别?

__block 本质上是局部变量的作用域修饰符,允许块修改在外部作用域中声明的局部变量的值。

您的 _hintExist 变量不是局部变量。这是一个全球性的。所以不需要 __block 修饰符。该块可以访问全局变量,就像同一文件中的任何其他代码一样。

如果您只是将 static 添加到您的 _hintExist 变量,它仍然是一个全局变量,但现在仅限于此文件。并且该块与文件中的任何其他代码一样,仍然可以访问和修改文件全局变量。

另一种选择是使 _hintExist 变量成为局部静态变量,如下所示:

- (void)showNotReachable
{
    static bool _hintExist = false;

    if (_hintExist) {
        return;
    }

    NSLog(@"Show a hint");

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        _hintExist = NO;
    });
}

假设它是您想要的,它也能正常工作。该变量的范围仅限于方法,但静态意味着该值独立于 class 的任何特定实例。同样,static 意味着您不需要 __block 修饰符。它就像一个全局但只在方法内部。

顺便说一句 - 关于通用命名约定的小说明。除实例变量外,不要对变量使用前导下划线。

根据安迪在此答案下方的第二条评论更新:

您似乎真的想使用实例变量,因为您希望 class 的每个实例都以 _hintExistfalse 值开始。

将 ivar 添加到 @implementation 块:

@implementation WhateverClassThisIs {
    bool _hintExist;
}

更新后的showNotReachable方法:

- (void)showNotReachable
{
    if (_hintExist) {
        return;
    }

    NSLog(@"Show a hint");

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        _hintExist = NO;
    });
}

与全局变量和静态变量一样,实例变量不需要 __block 限定符。而且,默认情况下,_hintExist 的初始值为 false