我有以下一段代码,它使用 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。
最佳答案
From the best of my understanding, enumerateGroupsWithTypes is an asynchronous method, which means it runs on its own thread.
“异步”并不意味着“在自己的线程上运行”。在 iOS 中有几种方法可以实现异步。最常见的一种是使用运行循环。这并不是说该方法不生成线程;它可能。但是没有理由假设它确实如此,如果是这样,那是一个私有(private)的实现细节。正如您所说,您的 block 在主线程上运行,这是您在这里真正应该关心的唯一事情。
从您描述的症状来看,我怀疑它与这段代码有什么关系。这听起来更像是您的 View 加载代码中的错误。我会检查例程
loadView
, viewDidLoad
, initWithFrame:
, awakeFromNib
, viewWillAppear:
, 和 viewDidAppear:
.您很可能在错误的位置创建进度指示器,或者未能将其插入到 View 层次结构中,或者将其从 View 层次结构中删除。关于模拟缓慢的加载时间,我会推荐“大量图片”的方法。您应该能够以编程方式生成大量图片(您甚至可以一遍又一遍地复制同一张图片),所以这应该不会太糟糕。如果它是您的个人设备,这有点烦人,但这就是开发的本质。
关于iphone - 异步方法、 block 和 GCD,难以理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9268358/