什么';在iOS块和队列中运行多个任务的最佳实践是什么?

什么';在iOS块和队列中运行多个任务的最佳实践是什么?,ios,performance,cocoa-touch,objective-c-blocks,grand-central-dispatch,Ios,Performance,Cocoa Touch,Objective C Blocks,Grand Central Dispatch,我开始大量使用街区和队列,它们非常棒。我使用更少的代码,构建和维护起来也更容易。但我想知道性能如何。在一个例子中,我显示的屏幕上满是Flickr照片集的缩略图。代码迭代所有项目,并启动一个唯一的下载队列来同时下载每张照片。它工作得很好,但是我想知道我是否应该创建一个静态队列来下载照片,然后将这些下载块分配到同一个队列,以便它能够有效地管理这些块 我在这里上传了一个例子 具体实施内容如下。我很欣赏对更好性能的任何见解。(稍后,我想通过将文件放在tmp文件夹中来处理图像缓存,以便定期自动清除它们。

我开始大量使用街区和队列,它们非常棒。我使用更少的代码,构建和维护起来也更容易。但我想知道性能如何。在一个例子中,我显示的屏幕上满是Flickr照片集的缩略图。代码迭代所有项目,并启动一个唯一的下载队列来同时下载每张照片。它工作得很好,但是我想知道我是否应该创建一个静态队列来下载照片,然后将这些下载块分配到同一个队列,以便它能够有效地管理这些块

我在这里上传了一个例子

具体实施内容如下。我很欣赏对更好性能的任何见解。(稍后,我想通过将文件放在tmp文件夹中来处理图像缓存,以便定期自动清除它们。)

如何使用块管理并发任务?您是否创建静态队列并向共享队列分派块?或者下面的实现是否已经有效地隐式管理了我的所有任务

#import "UIImage+DownloadImage.h"

@implementation UIImage (DownloadImage)

+ (void)downloadImageWithURL:(NSURL *)imageURL andBlock:(void (^)(UIImage *image, NSError *error))returnImage {

    dispatch_queue_t callerQueue = dispatch_get_current_queue();
    dispatch_queue_t downloadQueue = dispatch_queue_create("Image Download Queue", NULL);
    dispatch_async(downloadQueue, ^{
        UIImage *image = nil;
        NSError *error = nil;

        // use the default cache policy to do the memory/disk caching
        NSMutableURLRequest *request = [NSMutableURLRequest 
                                        requestWithURL:imageURL 
                                        cachePolicy:NSURLRequestUseProtocolCachePolicy 
                                        timeoutInterval:15];

        NSHTTPURLResponse *response = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

        // 200 indicates HTTP success
        if (response.statusCode != 200) {
            data = nil;

            // set the error to indicate the request failed
            NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithFormat:@"Request failed with HTTP status code of %i", response.statusCode], NSLocalizedDescriptionKey, nil];
            error = [NSError errorWithDomain:@"UIImage+DownloadImage" code:response.statusCode userInfo:userInfo];
        }
        else if (!error && data) {
            image = [UIImage imageWithData:data];
        }

        // image will be nil if the request failed

        dispatch_async(callerQueue, ^{
            returnImage(image, error);
        });
    });
    dispatch_release(downloadQueue);
}

@end

每次创建一个1元素队列似乎效率很低,但如果在分析过程中显示为热点,我会感到惊讶


如果你在苹果的iOS论坛上搜索,你应该能够找到Quinn关于使用NSURLConnection“原始”而不是通过线程的讨论。

你正在队列上进行同步网络活动。这似乎是一个相当糟糕的想法,因为您正在阻塞线程并迫使GCD启动新线程来服务其他块。如果你同时下载20张图片,那么你的应用程序中会有20个被阻止的线程,还有一些线程需要实际工作。相反,您应该在单个工作线程上执行异步网络活动。甚至有一段苹果的示例代码可以做到这一点,尽管我一辈子都记不清它叫什么。

+1,下载应该使用异步API完成,如果可以的话,我会再加一个+1来表示奎因是“爱斯基摩人!”我已经使用了异步API,但现在由于GCD和本例中所示的块,我不必这样做。我在异步队列上运行下载,以便UI保持响应。使用块比实现许多方法和管理变量更优雅。也找不到奎因的讨论。那里有很多可供选择的。(它被钉在其类别的顶部)。感谢链接。奎因确实深入挖掘了我没有的细节。我仍然想知道,如果我使用的队列是静态的,所以所有的块都在一个队列上运行,而忽略了网络部分,那么是否会有区别。我仍然想以这样的方式使用块/队列。你有理由说在队列中进行网络活动是个坏主意吗?不是所有的东西都在队列中运行并且随时都可能被阻塞吗?我想我可以在优先级较低的队列上运行这些网络请求,但到目前为止,它似乎运行得相当好。我只是想知道我是否应该为所有20个请求使用一个队列。我必须对它进行实验和分析。@Brennan:你在队列中阻塞IO,特别是网络IO。这样做会阻塞整个线程,并迫使GCD启动新线程(这很昂贵)。当你可以在一个线程上运行所有网络活动时,绝对没有理由公然浪费资源。我的两分钱:@Brennan,在单独的队列上执行网络IO不仅不是个坏主意,而且是个好主意。我认为Kevin的意思是,为每个图像调用
dispatch\u queue\u create()
是不明智的。您应该创建一个队列,然后继续对该队列执行
dispatch\u async()
。我已经对为每个映像重新调用
dispatch\u queue\u create()
的概念进行了评论。看来你应该只做一次。此外,由于您询问最佳实践,苹果建议您在命名队列时应使用反向DNS表示法(例如“com.mycompany.myqueue”)。