块中使用的NSMutableArray实例

以下代码段使用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限定符,此代码仍然有效。

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对象只能通过指针访问,我们经常将指针称为对象。 这种区别在很大程度上并不重要; 这是有史以来的一次。

你混淆了变量和对象。 变量指向对象,但变量与它指向的对象不同。 __block存储说明符会影响变量存储,但对变量指向的对象实际上没有任何影响。 除了那个变量之外,任何数量的变量都可以指向该对象,并且它不关心它们的存储是什么样的 – 它只是在它们指向它时浮动在堆中。

所以,简而言之,你不是在改变变量 – 你正在改变对象。