我正在尝试在应用中实现iOS Background Fetch API。该应用程序从服务器下载JSON,调用-[UICollectionView reloadData]
,并为每个单元格,并在-collectionView:cellForItemAtIndexPath:
中异步下载图像。
在我的初始实现中,在调用application:performFetchWithCompletionHandler
之后,我会将系统传递的完成处理程序调用到reloadData
。多任务视图中的应用程序快照将显示空单元格,因为尚未下载图像。为了解决这个问题,我在reloadData之后删除了完成处理程序调用,写了一个小结构来跟踪已经下载了哪些单元格的图像,并且只有在下载了一定数量之后,我才会调用完成处理程序。
我使用视图控制器上的completionBlock
属性重新加载图像。应用程序委托设置该属性,然后在该视图控制器上调用reload
方法,然后调用其完成处理程序属性。我看起来像这样:
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
WSViewController *viewController = (WSViewController *)navController.topViewController;
viewController.completionBlock = ^(BOOL success, BOOL newData) {
if (!success) {
completionHandler(UIBackgroundFetchResultFailed);
} else if (success) {
if (newData) {
completionHandler(UIBackgroundFetchResultNewData);
} else {
completionHandler(UIBackgroundFetchResultNoData);
}
}
};
[viewController reload];
}
在测试期间,我发现以相对快速的连续执行后台提取会导致不调用完成处理程序。这很容易解释,因为completionBlock
属性被覆盖而旧的属性不会被调用。
所以,as advised in WWDC 2013 Session 204 "What's New With Multitasking",我删除了属性并决定将完成处理程序一直传递到我的代码中。 -reload
现在是-reloadWithCompletionBlock:
等。
但现在我仍然坚持如何在App Delegate中实现它。 View Controller有一个委托,其中一个方法- (void)didFinishDownloadingImages
由App Delegate实现。 这就是我想要调用完成处理程序的地方。但是我不能,因为没有办法在没有将它存储在属性中的情况下进入完成处理程序,从一开始就打败了我这样做的原因。
关于如何解决这个问题的任何想法?
答案 0 :(得分:0)
使用NSOperationQueue并将您的代码块移动到NSOperation的子类中 - 这将帮助您处理阻塞,丢弃多个请求以及处理所有这些类型的情况等情况。
因此,我不是编写内联块,而是移动到一个操作队列,这似乎有些提升,但实际上使这更容易处理。