实例变量和使用GCD的线程

时间:2012-08-07 20:34:22

标签: objective-c multithreading ios5 grand-central-dispatch

我最近为应用添加了线程,以便网络请求不会阻止用户界面。在这样做时,我发现我无法再像实现线程之前那样设置我的实例变量。我的实例变量是声明如下的属性:

@property (nonatomic, strong) NSMutableArray *currentTopPlaces;

以下是我错误地设置我的实例变量self.currentTopPlaces:

的方法
dispatch_queue_t downloadQueue = dispatch_queue_create("Flickr Top Places Downloader", NULL);
dispatch_async(downloadQueue, ^{
    __block NSArray *topPlaces = [FlickrFetcher topPlaces];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.tableRowCount = [topPlaces count];
        [[self currentTopPlaces] setArray:topPlaces];
    });

在我开始使用GCD之前,使用[self currentTopPlace] setArray:topPlaces]在阻止版本中运行良好。

现在,为了让事情正常工作,我必须这样设置:

dispatch_queue_t downloadQueue = dispatch_queue_create("Flickr Top Places Downloader", NULL);
dispatch_async(downloadQueue, ^{
    __block NSArray *topPlaces = [FlickrFetcher topPlaces];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.tableRowCount = [topPlaces count];
        self.currentTopPlaces = topPlaces;
    });

有人可以向我解释使用之间的区别:

[[self currentTopPlaces] setArray:topPlaces];

self.currentTopPlaces = topPlaces;

具体来说,为什么“setArray”调用在线程块中不起作用?

我认为Objective-C中的点符号是语法糖而不是强制性的。我想知道实现相同行为的“非糖”方式。

2 个答案:

答案 0 :(得分:5)

[self currentTopPlaces]self.currentTopPlaces实际上是相同的,但

[self.currentTopPlaces setArray:topPlaces]; // (1)
self.currentTopPlaces = topPlaces; // (2)

不是。 (1)将self.currentTopPlaces的所有元素替换为topPlaces的元素。 (2)为self.currentTopPlaces分配一个新值(如果不是 nil 则释放旧值)。

如果self.currentTopPlaces nil ,则会出现差异:(1)什么都不做,因为setArray:方法被发送到 nil 。 (2)为self.currentTopPlaces分配新值。

顺便说一下:您的代码中不需要__block修饰符,因为该块不会更改topPlaces的值。

答案 1 :(得分:2)

[[self currentTopPlaces] setArray:topPlaces];
self.currentTopPlaces = topPlaces;

这是两个完全不同的表达方式。第一个是写的,第二个是:

[self setCurrentTopPlaces:topPlaces];

如果你想用点表示法做第一个,那就是:

self.currentTopPlaces.array = topPlaces;