如何在iOS中异步下载多个图像而不影响UI?
我有100个URL,我想下载所有这些图片并保存在文档中。为了节省我所做的,我也可以做懒惰加载,但我无法下载所有与最短的时间和GUI不应该挂起 这样做的合适方法是什么如何在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:
感谢更好的用户网络,它将帮助您异步下载所有图像(无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保存了一个图像。但是这种技术太棒了,我会记住它,无论我有一个需要执行异步操作。