Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在iOS中异步下载多个图像而不影响UI?_Ios_Multithreading_Image_Asynchronous - Fatal编程技术网

如何在iOS中异步下载多个图像而不影响UI?

如何在iOS中异步下载多个图像而不影响UI?,ios,multithreading,image,asynchronous,Ios,Multithreading,Image,Asynchronous,我有100个URL,我想下载所有这些图片并保存在文档中。为了节省我所做的,我也可以做懒惰加载,但我无法下载所有与最短的时间和GUI不应该挂起 这样做的合适方法是什么 感谢更好的用户网络,它将帮助您异步下载所有图像(无GUI挂起) 更好的用户网络,它将帮助您异步下载所有图像(无GUI挂起) 使用SDWebImage。您可以从下面的url下载它 用于使用异步请求加载100个图像 for(int i=0; i<99; i++) { strImage=[[res valueForKey:

我有100个URL,我想下载所有这些图片并保存在文档中。为了节省我所做的,我也可以做懒惰加载,但我无法下载所有与最短的时间和GUI不应该挂起

这样做的合适方法是什么


感谢

更好的用户网络,它将帮助您异步下载所有图像(无GUI挂起)


更好的用户网络,它将帮助您异步下载所有图像(无GUI挂起)


使用SDWebImage。您可以从下面的url下载它

用于使用异步请求加载100个图像

for(int i=0; i<99; i++)
{
    strImage=[[res valueForKey:@"result"] objectAtIndex:i];
    if ([[strImage lowercaseString] hasSuffix:@".jpg"] || [[strImage lowercaseString] hasSuffix:@".png"])
    {
        //[HUD show:YES];
        NSURL *url=[[NSURL alloc]initWithString:strImage];
        NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
        [NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
        {
             thumbnail.image=[UIImage imageWithData:data];
        }];
    }
}

for(inti=0;i使用SDWebImage。您可以从下面的url下载它

用于使用异步请求加载100个图像

for(int i=0; i<99; i++)
{
    strImage=[[res valueForKey:@"result"] objectAtIndex:i];
    if ([[strImage lowercaseString] hasSuffix:@".jpg"] || [[strImage lowercaseString] hasSuffix:@".png"])
    {
        //[HUD show:YES];
        NSURL *url=[[NSURL alloc]initWithString:strImage];
        NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
        [NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
        {
             thumbnail.image=[UIImage imageWithData:data];
        }];
    }
}

用于(int i=0;i您可以使用AFHTTPClientto,这有一个在所有操作完成时调用的completionBlock。应该正是您要查找的内容。

您可以使用AFHTTPClientto,这有一个在所有操作完成时调用的completionBlock。应该正是您要查找的内容查找。

一个复杂的解决方案可能会变得相当复杂。下载和保存100个URL并不像下载一幅图像100次那么容易

在雄心勃勃但不太聪明的实现中,最棘手的问题是内存压力。第三方网络库不会自动为您解决这个问题

一种简单但可行的方法是以牺牲一点性能为代价来避免内存问题,它是按顺序执行下载和保存到磁盘操作。这确保了在任何时候只处理一个映像。因此,您可以对这种方法所需的最大内存进行安全的假设

解决方案可能如下所示:

假设您有一个异步方法,从给定URL加载图像数据:

typedef void (^load_completion_t)(NSData* data, NSError* error);
- (void) loadURL:(NSURL*)url completion:(load_completion_t)completionHandler;
这种方法会将整个图像数据加载到内存中。这并不是最好的方法,但是如果我们假设一幅图像总是适合内存,那么它就变成了一个简单的解决方案

此外,假设存在将数据保存到磁盘的同步方法:

- (void) saveData:(NSData*)data;
现在,给定一组URL,您可以按如下顺序加载和保存大量图像:

typedef void(^completion_t)(id result, NSError* error);

- (void) saveImagesWithURLs:(NSMutableArray*)urls 
         completion:(completion_t)completionHandler
{
    if ([urls count] > 0) {
        NSURL* url = [urls firstObject];
        [urls removeObjectAtIndex:0];
        [self loadURL:url completion:^(NSData* imageData, NSError*error){
            if (imageData) {
                [self saveData:imageData];
                [self saveImagesWithURLs:urls completion:completionHandler];
            } 
            else  {
               // handle error
            }
        }];
    }
    else {
        // finished
        if (completionHandler) {
            completionHandler(@"Images saved", nil);
        }
    }
}
上述方法是一个“异步循环”:

loadURL:completion
的完成处理程序将调用
saveImageSwithuls:completion:
,与递归调用非常相似。但是,这不是递归方法:当方法
saveImageSwithuls:completion:
的完成处理程序被执行时,
saveImageSwithuls:completion:
已经返回

给定一个URL数组属性:

@property (nonatomic, strong) NSArray* imageURLs;
您可以调用异步循环,如下所示:

[self saveImagesWithURLs:[self.imageURLs mutableCopy] 
              completion:^(id result, NSError*error){
    if (error) {
        // handle error
    }
    else {
        // result equals @"Images saved"
    }
}];

您可以从主线程调用此方法。它不会阻塞,因为它是异步的。我们还假设完成处理程序将在专用队列上调用,而不是在主线程上调用。

一个复杂的解决方案可能会变得非常复杂。下载和保存100个URL并不像下载一个图像100次那么简单。

在雄心勃勃但不太聪明的实现中,最棘手的问题是内存压力。第三方网络库不会自动为您解决这个问题

一种简单但可行的方法是以牺牲一点性能为代价来避免内存问题,它是按顺序执行下载和保存到磁盘操作。这确保了在任何时候只处理一个映像。因此,您可以对这种方法所需的最大内存进行安全的假设

解决方案可能如下所示:

假设您有一个异步方法,从给定URL加载图像数据:

typedef void (^load_completion_t)(NSData* data, NSError* error);
- (void) loadURL:(NSURL*)url completion:(load_completion_t)completionHandler;
这种方法会将整个图像数据加载到内存中。这并不是最好的方法,但是如果我们假设一幅图像总是适合内存,那么它就变成了一个简单的解决方案

此外,假设存在将数据保存到磁盘的同步方法:

- (void) saveData:(NSData*)data;
现在,给定一组URL,您可以按如下顺序加载和保存大量图像:

typedef void(^completion_t)(id result, NSError* error);

- (void) saveImagesWithURLs:(NSMutableArray*)urls 
         completion:(completion_t)completionHandler
{
    if ([urls count] > 0) {
        NSURL* url = [urls firstObject];
        [urls removeObjectAtIndex:0];
        [self loadURL:url completion:^(NSData* imageData, NSError*error){
            if (imageData) {
                [self saveData:imageData];
                [self saveImagesWithURLs:urls completion:completionHandler];
            } 
            else  {
               // handle error
            }
        }];
    }
    else {
        // finished
        if (completionHandler) {
            completionHandler(@"Images saved", nil);
        }
    }
}
上述方法是一个“异步循环”:

loadURL:completion
的完成处理程序将调用
saveImageSwithuls:completion:
,与递归调用非常相似。但是,这不是递归方法:当方法
saveImageSwithuls:completion:
的完成处理程序被执行时,
saveImageSwithuls:completion:
已经返回

给定一个URL数组属性:

@property (nonatomic, strong) NSArray* imageURLs;
您可以调用异步循环,如下所示:

[self saveImagesWithURLs:[self.imageURLs mutableCopy] 
              completion:^(id result, NSError*error){
    if (error) {
        // handle error
    }
    else {
        // result equals @"Images saved"
    }
}];

您可以从主线程调用此方法。它不会阻塞,因为它是异步的。我们还假设,完成处理程序将在专用队列上调用,而不是在主线程上调用。

这并没有回答如何有效地下载100个URL而不面临内存压力的问题。这并没有回答问题stion,如何有效地下载100个URL,而无需面对内存压力。我发现这种方法最容易理解,也最容易在我正在开发的应用程序中实现。在我的例子中,我碰巧也在基于URL保存图像。但这种技术太棒了,我无论如何都会记住它我有一个需要执行异步操作的循环。我发现这种方法最容易理解,也最容易在我正在开发的应用程序中实现。在我的例子中,我碰巧也基于URL保存了一个图像。但是这种技术太棒了,我会记住它,无论我有一个需要执行异步操作。