以下代码段使用GCD计算一组整数并将它们存储在数组中。
factArray = {1!,2!,... n!}其中k!指代阶乘(k)= k *(k-1)* ... * 2 * 1.
我想知道为什么我可以在块中添加对象factArray变量(NSMutableArray的实例),尽管factArray没有使用__block限定符声明。
NSUInteger n = 10;
NSMutableArray *factArray = [[NSMutableArray alloc] initWithCapacity:n];
__block NSUInteger temp = 1;
dispatch_apply(n,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^(size_t s) {
NSUInteger w;
temp *= floor(s) + 1;
w = temp;
[factArray addObject:@(w)];
});
__block NSArray *sortedArray;
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
sortedArray = [factArray sortedArrayUsingComparator:^NSComparisonResult(NSNumber *n1, NSNumber *n2) {
return [n1 compare:n2];
}];
NSLog(@"%@", sortedArray);
});
当然,如果我们添加__block限定符,此代码仍然有效。
答案 0 :(得分:6)
factArray
是一个变量,例如temp
。这是指针;它保存了其他内存的地址。 Block获取该指针的副本,就像它获得temp
的副本一样。但是,指向的对象不会被复制。它停留在同一个地方,仍然是NSMutableArray
。您可以通过指针向它发送消息;这不会改变指针的值。它仍然指向同一个地方,并且可以在不更改指针的情况下修改对象的内容。
如果您想要删除现有数组并创建一个新数组,并调用该数组factArray
:
dispatch_apply(n, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^(size_t s) {
factArray = [NSMutableArray array];
});
然后你将改变指针的值,然后你需要__block
说明符。
通俗地说,由于ObjC对象只能通过指针访问,我们经常将指针称为对象。区别在很大程度上是不重要的;这是其中一次。
答案 1 :(得分:3)
你混淆了变量和对象。变量指向对象,但变量与它指向的对象不同。 __block
存储说明符会影响变量存储,但对变量指向的对象实际上没有任何影响。除了那个变量之外,任何数量的变量都可以指向该对象,并且它不关心它们的存储是什么样的 - 它只是在它们指向它时浮动在堆中。
因此,简而言之,您不会更改变量 - 您正在改变对象。