嵌套块导致什么问题?

时间:2014-01-03 09:34:56

标签: objective-c objective-c-blocks

使用GCD时,我有时会使用块内的块。 除了保留周期之外,这样做会出现什么问题?

请详细说明。外部块是复制整个内存,包括局部变量,内部块复制外部块刚刚复制的每个局部变量,还是局部变量只在内部块中?那么会出现什么问题?

1 个答案:

答案 0 :(得分:2)

首先,块“虚拟地”复制程序的所有可到达的本地变量。当然,这是由编译器优化的。只复制在块内使用的变量。

第二:当定义块时,它们以它们具有的状态被复制。这意味着:当执行定义块文字的语句时。 (^{…}的陈述,而不是…()的陈述)

通过一个例子,它更容易理解:

int outerInnerVar = 1;
int innerVar = 1;
__block int uncapturedVar = 1;
void (^outer)(void) =
^{
    NSLog(@"outer: %ld", (long)outerInnerVar);
    uncapturedVar = 3;
    void (^inner)(void) =
    ^{
        NSLog(@"inner: %ld", (long)outerInnerVar);
        NSLog(@"inner: %ld", (long)innerVar);
        NSLog(@"inner: %ld", (long)uncapturedVar);
    };
    uncapturedVar = 4;
    inner();
};
outerInnerVar = 2;
innerVar = 2;
uncapturedVar = 2;
outer();

<强> outerInnerVar

外部块以值1捕获outerInnerVar。内部块文字捕获不执行任何操作,因为它未执行。这是在最后一行完成的。但由于外部块已将outerInnerVar捕获到其闭包中,因此现在执行的内部块定义使用值为1的outerInnerVar执行。因此内部块使用值{1}捕获outerInnerVar 1,也是。

→您获得两个日志,其中outerInnerVar为1。

<强> innerVar

也许您期望innerVar有不同的结果。但它在内部外部块中使用,因为它在内部块内部使用,内部块位于外部块内部。所以外部块也将innerVar放入其(外部)闭包中。结果是一样的:

innerVar获得1的日志。 (实际上这是另一个outerInnerVar。)

<强> uncapturedVar

uncapturedVar显然不在外部区块的封闭中。所以我们很清楚,我们不会使用值1来记录它。但是有2,3或4?

uncapturedVar是一个块变量。这定义了它的行为,而不是块。因此,它是所有嵌套(和连续)块内的块变量。因此,在执行块本身(而不是其定义)之前,变量的最后一个状态将是find。

→您获得uncapturedVar的4日志。

就我个人而言,我会期待innerVar的不同行为。但我认为通过外部区域静默捕获它是合理的。

当物理完成副本时,实现细节。