块中使用的NSMutableArray实例

时间:2014-01-04 00:47:42

标签: ios objective-c block

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

2 个答案:

答案 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存储说明符会影响变量存储,但对变量指向的对象实际上没有任何影响。除了那个变量之外,任何数量的变量都可以指向该对象,并且它不关心它们的存储是什么样的 - 它只是在它们指向它时浮动在堆中。

因此,简而言之,您不会更改变量 - 您正在改变对象。