Anu*_*har 8 nsoperationqueue ios5 afnetworking
我正在处理一项任务(仅限iOS5 +),涉及从服务器下载数千张图像.图像属于某些类别,每个类别可以有数百个图像.我需要做的是: -
1)如果应用程序处于活动状态,请确保应用程序在后台下载任何丢失的图像(即使用户正在浏览应用程序中与照片无关的其他某些区域).
2)当用户点击照片类别时,必须将该类别中的图像作为高优先级下载,因为那些是需要立即可见的图像.
所有上述操作仅在图像尚未脱机可用时才会发生.下载后,图像将从本地存储中使用.
要解决这个问题,我使用的逻辑是: -
1)在AppDelegate.m中applicationDidBecomeActive
,我开始下载任何丢失的图像.为此,我进行了核心数据查询,找出缺少的图像,并开始在具有BACKGROUND优先级的线程中下载它们.像这样: -
dispatch_queue_t imageDownloadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_async(imageDownloadQueue, ^{
[DataDownloader downloadMissingImages];
});
dispatch_release(imageDownloadQueue);
Run Code Online (Sandbox Code Playgroud)
该downloadMissingImages
代码如下所示: -
NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
downloadQueue.maxConcurrentOperationCount = 20;
for(MyImage *img in matches)
{
NSURLRequest *request = [NSURLRequest requestWithURL:img.photoUrl];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request success:^(UIImage *image) {
[MyImage imageFromAPI:image inManagedObjectContext:document.managedObjectContext];
NSLog(@"Successfully downloaded image for %@", img.title);
}];
[downloadQueue addOperation:operation];
}
Run Code Online (Sandbox Code Playgroud)
这可行,但它会阻止主UI和应用程序崩溃一段时间后.这是我尝试下载大约700张图片的时候.随着更多的图像,它肯定会崩溃.
2)当用户点击某个类别时,我需要先下载这些图像,因为它们必须立即显示给用户.我不知道如何中断missImages调用并告诉它开始在其他人之前下载某些图像.
所以,基本上,我需要在后台下载所有丢失的图像,但如果用户正在浏览照片类别,那些图像必须在下载队列中具有高优先级.
我不知道如何有效地工作.有什么想法吗?
崩溃日志看起来像这样
PAPP(36373,0xb065f000) malloc: *** mmap(size=16777216) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
PAPP(36373,0xb065f000) malloc: *** mmap(size=16777216) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Jun 24 11:39:45 MacBook-Pro.local PAPP[36373] <Error>: ImageIO: JPEG Insufficient memory (case 4)
Run Code Online (Sandbox Code Playgroud)
提前致谢.
关于崩溃,我猜您的应用程序因以下两种选择之一而被终止:
应用程序变得无响应(因此不响应 iOS 哨兵进程);
循环中使用了太多内存,创建了 700 多个请求操作。
为了弄清楚到底发生了什么,您应该提供有关崩溃的更多信息(控制台日志)。在任何情况下,修复方法都是以每个 10 或 20 个块的形式加载图像(如果您愿意,您甚至可以 1 个 1 个,我认为这没有太大问题)。
关于第二点,这个呢:
在主线程中下载更高优先级的图像(当然,通过异步下载以避免阻塞 UI);
在开始下载“离线”图像之前,您可以检查该图像是否已经通过“更高优先级”下载同时下载。
为了很好地处理第 2 点,您可能需要对自定义操作进行排队,而不是AFImageRequestOperation
在实际下载之前进行检查。
编辑:
关于分块下载图像,您可以使用调度组对网络操作进行分组:
dispatch_group_t group = dispatch_group_create();
<your_core_data_query>
for (...) {
dispatch_group_enter(group);
NSURLRequest *request = [NSURLRequest requestWithURL:img.photoUrl];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request success:^(UIImage *image) {
[MyImage imageFromAPI:image inManagedObjectContext:document.managedObjectContext];
NSLog(@"Successfully downloaded image for %@", img.title);
dispatch_group_leave(group); //<== NOTICE THIS
}];
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
Run Code Online (Sandbox Code Playgroud)
在此示例中,我使用调度组对多个异步操作进行分组并等待它们全部执行;返回时dispatch_group_wait
,您可以执行另一轮(查询核心数据然后分派操作)。
关于您的另一个问题(如何检查较高优先级队列是否已经下载了某个图像),您应该在执行每个之前执行核心数据查询AFImageRequestOperation
;一种可能性是派生您自己的类并覆盖start
执行检查的方法。
在这两个帐户上,您可以通过一次下载一个图像来简化所有这一切的逻辑(即,循环for (...)
不会存在;您只需查询下一张图像来下载并下载它;在下载之前检查它是否存在)已经在那了。
我建议走这条更简单的路。
希望能帮助到你。
归档时间: |
|
查看次数: |
3905 次 |
最近记录: |