块和变量

时间:2012-02-10 08:47:02

标签: objective-c objective-c-blocks

目前我正在探索块机会,我读了十多次苹果文档)但我无法理解博客示例和代码中的块行为。我知道__block修饰符。所以请看几个我的例子,并说明它为什么起作用:

1)不工作。需要__block,因为我想修改object.And自我保留(正确吗?)并且在博客中我被保留自我循环吓坏了。是吗?

NSDictionary *result = nil;
dispatch_async(queue, ^{
    result = [self sendRequest:apiRequest];
});

2)不工作。我不了解dispatch_async的变量范围(dispatch_get_main_queue(),^ {});.它是否在主线程中看到所有局部变量,或者它是与主线程分开的块,但在主线程中是否已被删除?像dispatch_async(dispatch_get_main_queue()^ {});复制dispatch_async(queue,^ {})中的所有局部变量;并将信号量切换到主线程。

NSDictionary *result = nil;
dispatch_async(queue, ^{
    NSDictionary *data = [self sendRequest:apiRequest];
    dispatch_async(dispatch_get_main_queue(), ^{
        result=[data retain];
    });
}); 

3)博客和斯坦福的课程中的例子特别让我感到困惑,因为他们有效。

- (void)viewWillAppear:(BOOL)animated
{
    dispatch_queue_t downloadQueue = dispatch_queue_create(“image downloader”, NULL);
    dispatch_async(downloadQueue, ^{
         NSData *imageData = [NSData dataWithContentsOfURL:networkURL];
         dispatch_async(dispatch_get_main_queue(), ^{
             UIImage *image = [UIImage imageWithData:imageData];
             self.imageView.image = image;
             self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
             self.scrollView.contentSize = image.size;
         });
    });
    dispatch_release(downloadQueue);
}

我不明白,因为首先他们在文章和课程中没有提到关于__block的自我,第二个代码修改了变量,但是通过属性和编译器不会发誓变量不可分配和属性更改引用,而不是值。最后它有效。提前谢谢。

2 个答案:

答案 0 :(得分:5)

老问题,但我觉得新读者可能会从比现在更精确的答案中受益:

1)result是指向对象的指针,而不是对象本身。前置__block是必要的,因为该指针已分配给块内。修改由块外部的指针变量指向的对象不是问题,例如

NSMutableDictionary* result = [NSMutableDictionary new];

然后通过[result setObject...]修改块内的对象就没问题了。这就是为什么3)工作的原因:只修改self指向的对象的变量。永远不会将指针self分配给。

关于块下引用的对象在ARC下的保留,请参见例如:

ARC with blocks and retain cycles

ARC, Blocks and Retain Cycles

blocks and ARC - copy or crash with release build (caused by optimization level)

答案 1 :(得分:2)

1)是的,您需要声明:

__block NSDictionary *results = nil;

如果您正在使用ARC,它应该自动负责保留和释放结果对象。如果不使用ARC,那么首先执行retain,然后执行release作为您在块中执行的最后操作。

2)一个块应该可以看到它的父级范围内可用的所有变量/对象。因此,在一个方法中,您应该能够看到该方法的所有局部变量以及该方法所属的对象(如self)。

3)对此不太确定。一旦你离开函数/方法,变量就会消失(大多数块都被称为,而不是完成执行),其中任何属于self的一部分获胜& #39;吨。也许这与它有关。