这是一个棘手的问题,我无法解决。
我知道 Obj-C 块本身不是闭包,它们的实现在某种程度上与 Javascript 闭包不同,但我仍然会使用 Javascript 示例来展示我想要完成的事情(熟悉 Javascript 的人会明白) .
在 Javascript 上,您可以创建如下所示的“函数工厂”:
//EXAMPLE A
var _arr = [], i = 0;
for(;i<8;++i) {
_arr[i] = function() {
console.log('Result:' + i);
};
}
//BY THE END OF THIS LOOP i == 7
_arr[0]();
_arr[1]();
_arr[2]();
...
_arr[7]();
它用相应的函数填充一个名为 _arr 的数组,然后评估所有这些。请注意,上述代码的结果将输出...
Result: 7
Result: 7
Result: 7
...
Result: 7
... '7' 在所有函数中,这是正确的,因为当函数被评估时 i 的值等于 8,即使在它们被创建时 i 的值是 0...7,这里我们得出结论 i 是通过引用而不是值传递的。
如果我们想“修复”这个问题并让每个函数在创建时使用 i 的值,我们可以编写如下代码:
//EXAMPLE B
var _arr = [], i = 0;
for(;i<8;++i) {
_arr[i] = (function(new_i){
return function() {
console.log(new_i);
};
})(i); //<--- HERE WE EVALUATE THE FUNCTION EACH TIME THE LOOP ITERATES, SO THAT EVERYTHING INSIDE OF THIS 'RETAINS' THE VALUES 'AT THAT MOMENT'
}
//BY THE END OF THIS LOOP i == 7, BUT IT DOESN'T MATTER ANYMORE
_arr[0]();
_arr[1]();
_arr[2]();
...
_arr[7]();
它不是直接创建最终函数,而是使用中间闭包返回最终函数,其中正确的值“固定”在其中;因此将返回:
Result: 0
Result: 1
Result: 2
...
Result: 7
现在...
我试图通过使用 Objective-C 块来做同样的事情。
这是示例 A 的代码(在 Obj-C 中):
NSMutableArray *_arr = [NSMutableArray arrayWithCapacity:0];
int i = 0;
for(;i<8;++i) {
[_arr addObject:^{
NSLog(@"Result: %i", i);
}];
}
//BY THE END OF THIS LOOP i == 7
[_arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
((void (^)())obj)();
}];
这将输出...
Result: 7
Result: 7
...
Result: 7
...这也是正确的,因为该函数实际上包含对 i 的引用。
问题是,我应该如何重写上面的循环以模拟示例 B 中显示的行为?(我保留了它在创建函数时的价值)
我试过这样写循环:
for(;i<8;++i) {
[_arr addObject:^(int new_i){
return ^{
NSLog(@"Result: %i", new_i);
};
}(i)];
}
但是它在编译时给出了以下错误:Returning block that lives on the local stack
谢谢,最好的;D!