异步方法,块和GCD,无法理解

时间:2012-02-13 21:32:26

标签: iphone objective-c ios cocoa-touch objective-c-blocks

我有以下代码片段,它使用ALAssets库将用户相册存储到一个数组中,以便它们可以像照片应用程序一样填充在表格中:

- (void) loadAlbums
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [[self activityIndicator] startAnimating];

    [[self library] enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop)
    {
        if (group == nil)
        {
            [[self activityIndicator] stopAnimating]; 
            [[self tableView] reloadData];

            return;
        }

        [[self albums] addObject:group];
    }
    failureBlock:^(NSError *error) 
    {
        UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Album Error: %@", [error description]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];
    }];

    [pool release];
}

据我所知,enumerateGroupsWithTypes是一个异步方法,这意味着它在自己的线程上运行。但是,block参数在主线程上运行。 随着代码排在首位,我的活动指标出现问题。当第一次运行viewcontroller此方法时,activityindicator工作正常,但是如果我从堆栈弹出viewcontroller(即按下后退按钮)并重新加载它,活动指示器没有出现(尽管我在玩isHidden等)。所以我有一些问题:

1)任何人都能了解活动指标可能出现的问题吗?

2)除了使用[NSThread sleepWithDuration]NSTimer之外,什么是模拟慢加载时间而不必创建包含大量图片的相册的最佳方式?

3)如果加载照片确实需要一段时间,我的应用的用户界面会被阻止,还是用户仍然可以与之互动?因为它在一个单独的线程上运行,所以它似乎应该,但我不确定。

更新:有关如何改善这一点的任何想法或资源?我已经阅读了Apple的线程编程和并发人员并观看了很多WWDC视频,但我仍然无法掌握如何处理这样的绝对简单的情况,我只是试图不阻止用户的UI。

1 个答案:

答案 0 :(得分:3)

  

据我所知,enumerateGroupsWithTypes是一个异步方法,这意味着它在自己的线程上运行。

“异步”并不意味着“在自己的线程上运行”。在iOS中有几种异步方式。其中最常见的是使用run循环。这并不是说这种方法不会生成线程;它可能。但没有理由认为它确实如此,如果确实如此,那就是私有的实现细节。正如你所说,你的块在主线程上运行,这是你唯一应该关注的事情。

根据您描述的症状,我怀疑它与此代码有什么关系。这听起来更像是您加载代码的视图中的错误。我会检查例程loadViewviewDidLoadinitWithFrame:awakeFromNibviewWillAppear:viewDidAppear:。您很可能在错误的位置创建进度指示器,或者未将其插入到视图层次结构中,或者从视图层次结构中删除它。

关于模拟慢加载时间,我建议使用“大量图片”方法。您应该能够以编程方式生成大量图片(您甚至可以反复复制相同的图片),所以这不应该太糟糕。如果它是你的个人设备有点烦人,但这就是开发的本质。