Objective-C当使用__block修饰符捕获变量时,如何在块内维护初始值

时间:2016-01-13 01:25:59

标签: ios objective-c block static-variables

更新了问题我让情况更加清晰,因此您“需要”从块中访问原始值。

我不知道以下代码是否有任何实际用途,但仅仅为了学习和实验,请考虑以下内容:

__block int one = 1;
int(^capture)() = ^{
    int copiedOne = one;    // Copy one
    ++one;  // Add one
    return copiedOne;
};
NSLog(@"one: %i", one);  // one = 1
NSLog(@"copied one: %i", capture());  // Returns copiedOne = 1, one is now 2
NSLog(@"one after calling block: %i", one); // one = 2

one += 10;  // one = 12

NSLog(@"one: %i", one);  // Prints 12
NSLog(@"copied one: %i", capture());  // Returns copiedOne = 12, one is now 13
NSLog(@"one after calling block: %i", one); // one = 13

如果你想保持块内的初始值1,但也能够修改块内的one(我不知道。也许有一天你可能需要这种行为),还有另外一种方法,就是将一个值封装在静态NSNumber变量中,如下所示?

如果oneClassA实例的私有属性,则可能需要此行为,但您需要ClassB的实例来更新ClassA实例的属性获得one的原始值。您可以从capture调用ClassB并实现上述行为,同时仍然可以访问one的属性ClassA的原始值。

__block int one = 1;
int(^capture)() = ^{
    static NSNumber *copiedOne = nil;
    if (!copiedOne) {
        copiedOne = @(one);    // Copy one
    }
    ++one;  // Add one
    return [copiedOne intValue];
};
NSLog(@"one: %i", one);  // one = 1
NSLog(@"copied one: %i", capture());  // Returns copiedOne = 1, one is now 2
NSLog(@"one after calling block: %i", one); // one = 2

one += 10;  // one = 12

NSLog(@"one: %i", one);  // Prints 12
NSLog(@"copied one: %i", capture());  // Returns copiedOne = 1, one is now 13
NSLog(@"one after calling block: %i", one); // one = 13

1 个答案:

答案 0 :(得分:0)

该块捕获在其周围声明的任何变量值,无论您是否使用__block声明。 __block声明允许您更改该变量内的值。它本质上改变了块本身看到该变量的方式,没有__block声明它将被视为块的静态。

因此,将原始的一个变量保留原样并且不将其声明为__block是有意义的。然后在创建块之前复制该变量,并使其成为您要修改的块。

int one = 1;
__block copiedOne = one;
void(^capture)() = ^{
     ++CopiedOne;  // Add one
     NSLog(@"copiedOne: %i, one: %i", copiedOne, one);
};

来自Apple Docs ......

  

因为Integer被声明为__block变量,所以它的存储与块声明共享。

Link to docs here