使用GCD时,我有时会使用块内的块。 除了保留周期之外,这样做会出现什么问题?
请详细说明。外部块是复制整个内存,包括局部变量,内部块复制外部块刚刚复制的每个局部变量,还是局部变量只在内部块中?那么会出现什么问题?
答案 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
的不同行为。但我认为通过外部区域静默捕获它是合理的。
当物理完成副本时,实现细节。