Ios 将映像异步下载到NSData和缓存
首先,这不是一个重复的问题。我已经阅读了许多关于堆栈溢出的问题,但它们并没有帮助我完全解决问题 我正在从web服务下载图像。因为没有人喜欢UI被暂停,所以我使用线程分别下载图像Ios 将映像异步下载到NSData和缓存,ios,objective-c,nsdata,grand-central-dispatch,Ios,Objective C,Nsdata,Grand Central Dispatch,首先,这不是一个重复的问题。我已经阅读了许多关于堆栈溢出的问题,但它们并没有帮助我完全解决问题 我正在从web服务下载图像。因为没有人喜欢UI被暂停,所以我使用线程分别下载图像 NSURL *imageUrl = [NSURL URLWithString:storyImageURL]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ thumbnailData = [NS
NSURL *imageUrl = [NSURL URLWithString:storyImageURL];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
thumbnailData = [NSData dataWithContentsOfURL:imageUrl];
dispatch_async(dispatch_get_main_queue(), ^{
thumbnail = [UIImage imageWithData:thumbnailData];
});
});
如果我完全按照上面的方式使用代码,UI将不会停止,直到它从web服务获取数据,但是图像不会被缓存
如果我不使用线程,那么UI将暂停,但是使用NSCoding方法(归档)缓存图像
我的问题是:如何使用线程并同时缓存缩略图?请不要建议任何第三方图书馆
更新:反复阅读代码后,我可能会想到两个问题:
1) 看起来在线程下载完图像之前调用了NSKeyedArchiver和NSKeyedUnarchiver,但这只是一个猜测。在单独的存储文件中,我使用NSKeyedArchiver和NSKeyedUnachiver:
- (RSSChannel *)fetchRSSFeedWithCompletion:(void (^)(RSSChannel *, NSError *))block
{
NSURL *url = [NSURL URLWithString:@"http://techcrunch.com/feed"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
RSSChannel *channel = [[RSSChannel alloc] init];
TheConnection *connection = [[TheConnection alloc] initWithRequest:req];
//[connection setCompletionBlock:block];
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
cachePath = [cachePath stringByAppendingPathComponent:@"HAHAHA.archive"];
RSSChannel *cachedChannel = [NSKeyedUnarchiver unarchiveObjectWithFile:cachePath];
if (!cachedChannel)
cachedChannel = [[RSSChannel alloc] init];
RSSChannel *channelCopy = [cachedChannel copy];
[connection setCompletionBlock:^(RSSChannel *obj, NSError *err) {
if (!err) {
[channelCopy addItemsFromChannel:obj];
[NSKeyedArchiver archiveRootObject:channelCopy toFile:cachePath];
}
block(channelCopy, err);
}];
[connection setXmlRootObject:channel];
[connection start];
return cachedChannel;
}
2) 我能想到的第二个问题是,在尝试从缓存中解码缩略图后,UI没有刷新。是否将
thumbnailData
保存为实例变量?在分派之前,请检查实例变量是否已设置,如果已设置,请返回该值。如果没有,则运行分派块并将其另存为实例变量。假设您的目标是iOS 5+,最自然的解决方案是使用NSURLCache
和NSURLConnection+sendAsynchronousRequest:queue:completionHandler:
。第三方解决方案通常只是忽略这些方法,要么是出于无知,要么是出于支持iOS 4的愿望,所以您的选择要么是将这些东西的维护工作有效地外包给苹果,要么是信任第三方,要么是花自己的时间在上面
例如
NSURLCache
在iOS 5之前存在,但只是一个内存缓存。因为它也是一个磁盘缓存。试试这个
NSURL *imageUrl = [NSURL URLWithString:storyImageURL];
UIButton *btnThumbnail = [[UIButton alloc] initWithFrame:CGRectMake(0, 10, 180, 280)];
[self downloadingServerImageFromUrl:btnThumbnail AndUrl:imageUrl];
[btnThumbnail addTarget:self action:@selector(onSelectEPaper:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:viewPaperBg];
- (void)onSelectEPaper:(id)sender
{
}
-(void)downloadingServerImageFromUrl:(UIButton*)imgView AndUrl:(NSString*)strUrl
{
// strUrl = [strUrl encodeUrl];
// strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString* theFileName = [NSString stringWithFormat:@"%@.jpg",[[strUrl lastPathComponent] stringByDeletingPathExtension]];
NSFileManager *fileManager =[NSFileManager defaultManager];
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"tmp/%@",theFileName]];
imgView.backgroundColor = [UIColor darkGrayColor];
UIActivityIndicatorView *actView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[imgView addSubview:actView];
[actView startAnimating];
CGSize boundsSize = imgView.bounds.size;
CGRect frameToCenter = actView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
actView.frame = frameToCenter;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSData *dataFromFile = nil;
NSData *dataFromUrl = nil;
dataFromFile = [fileManager contentsAtPath:fileName];
// NSLog(@"%@",fileName);
if(dataFromFile==nil){
// NSLog(@"%@",strUrl);
NSString *url =[strUrl stringByReplacingOccurrencesOfString:@"\n" withString:@""];
url=[url stringByReplacingOccurrencesOfString:@"\t" withString:@""];
url=[url stringByReplacingOccurrencesOfString:@" " withString:@""];
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// dataFromUrl=[[[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]] autorelease];
// dataFromUrl=[[NSData dataWithContentsOfURL:[NSURL URLWithString:url]] autorelease];
NSError* error = nil;
// NSLog(@"%@", [NSURL URLWithString:url]);
dataFromUrl = [NSData dataWithContentsOfURL:[NSURL URLWithString:url] options:NSDataReadingUncached error:&error];
if (error) {
NSLog(@"%@", [error localizedDescription]);
} else {
// NSLog(@"Data has loaded successfully.");
}
}
dispatch_sync(dispatch_get_main_queue(), ^{
if(dataFromFile!=nil){
// imgView.image = [UIImage imageWithData:dataFromFile];
[imgView setBackgroundImage:[UIImage imageWithData:dataFromFile] forState:UIControlStateNormal];
}else if(dataFromUrl!=nil){
// imgView.image = [UIImage imageWithData:dataFromUrl];
[imgView setBackgroundImage:[UIImage imageWithData:dataFromUrl] forState:UIControlStateNormal];
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"tmp/%@",theFileName]];
BOOL filecreationSuccess = [fileManager createFileAtPath:fileName contents:dataFromUrl attributes:nil];
if(filecreationSuccess == NO){
// NSLog(@"Failed to create the html file");
}
}else{
// imgView.image = [UIImage imageNamed:@"no_image.jpg"];
[imgView setBackgroundImage:[UIImage imageNamed:@"no_image.jpg"] forState:UIControlStateNormal];
}
[actView removeFromSuperview];
// [actView release];
// [imgView setBackgroundColor:[UIColor clearColor]];
});
});
}
NSURL*imageUrl=[NSURL-URLWithString:storyImageURL];
UIButton*btnThumbnail=[[UIButton alloc]initWithFrame:CGRectMake(0,10,180,280)];
[自下载ServerImageFromURL:BTN缩略图和URL:imageUrl];
[btnThumbnail addTarget:self action:@selector(onselectepper:)for controlEvents:UIControlEventTouchUpInside];
[self.view addSubview:viewPaperBg];
-(无效)onSelectEPaper:(id)发件人
{
}
-(void)下载ServerImagefromURL:(UIButton*)imgView和URL:(NSString*)strUrl
{
//strUrl=[strUrl encodeUrl];
//strUrl=[strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString*文件名=[NSString stringWithFormat:@“%@.jpg”,[[strUrl lastPathComponent]stringByDeletingPathExtension];
NSFileManager*fileManager=[NSFileManager defaultManager];
NSString*文件名=[NSHomeDirectory()stringByAppendingPathComponent:[NSString stringWithFormat:@“tmp/%@”,文件名]];
imgView.backgroundColor=[UIColor darkGrayColor];
UIActivityIndicatorView*actView=[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[imgView添加子视图:actView];
[actView startAnimating];
CGSize boundsSize=imgView.bounds.size;
CGRect frameToCenter=actView.frame;
//水平居中
if(frameToCenter.size.width NSURL *imageUrl = [NSURL URLWithString:storyImageURL];
UIButton *btnThumbnail = [[UIButton alloc] initWithFrame:CGRectMake(0, 10, 180, 280)];
[self downloadingServerImageFromUrl:btnThumbnail AndUrl:imageUrl];
[btnThumbnail addTarget:self action:@selector(onSelectEPaper:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:viewPaperBg];
- (void)onSelectEPaper:(id)sender
{
}
-(void)downloadingServerImageFromUrl:(UIButton*)imgView AndUrl:(NSString*)strUrl
{
// strUrl = [strUrl encodeUrl];
// strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString* theFileName = [NSString stringWithFormat:@"%@.jpg",[[strUrl lastPathComponent] stringByDeletingPathExtension]];
NSFileManager *fileManager =[NSFileManager defaultManager];
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"tmp/%@",theFileName]];
imgView.backgroundColor = [UIColor darkGrayColor];
UIActivityIndicatorView *actView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[imgView addSubview:actView];
[actView startAnimating];
CGSize boundsSize = imgView.bounds.size;
CGRect frameToCenter = actView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
actView.frame = frameToCenter;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSData *dataFromFile = nil;
NSData *dataFromUrl = nil;
dataFromFile = [fileManager contentsAtPath:fileName];
// NSLog(@"%@",fileName);
if(dataFromFile==nil){
// NSLog(@"%@",strUrl);
NSString *url =[strUrl stringByReplacingOccurrencesOfString:@"\n" withString:@""];
url=[url stringByReplacingOccurrencesOfString:@"\t" withString:@""];
url=[url stringByReplacingOccurrencesOfString:@" " withString:@""];
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// dataFromUrl=[[[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]] autorelease];
// dataFromUrl=[[NSData dataWithContentsOfURL:[NSURL URLWithString:url]] autorelease];
NSError* error = nil;
// NSLog(@"%@", [NSURL URLWithString:url]);
dataFromUrl = [NSData dataWithContentsOfURL:[NSURL URLWithString:url] options:NSDataReadingUncached error:&error];
if (error) {
NSLog(@"%@", [error localizedDescription]);
} else {
// NSLog(@"Data has loaded successfully.");
}
}
dispatch_sync(dispatch_get_main_queue(), ^{
if(dataFromFile!=nil){
// imgView.image = [UIImage imageWithData:dataFromFile];
[imgView setBackgroundImage:[UIImage imageWithData:dataFromFile] forState:UIControlStateNormal];
}else if(dataFromUrl!=nil){
// imgView.image = [UIImage imageWithData:dataFromUrl];
[imgView setBackgroundImage:[UIImage imageWithData:dataFromUrl] forState:UIControlStateNormal];
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"tmp/%@",theFileName]];
BOOL filecreationSuccess = [fileManager createFileAtPath:fileName contents:dataFromUrl attributes:nil];
if(filecreationSuccess == NO){
// NSLog(@"Failed to create the html file");
}
}else{
// imgView.image = [UIImage imageNamed:@"no_image.jpg"];
[imgView setBackgroundImage:[UIImage imageNamed:@"no_image.jpg"] forState:UIControlStateNormal];
}
[actView removeFromSuperview];
// [actView release];
// [imgView setBackgroundColor:[UIColor clearColor]];
});
});
}
RSSChannel *channelCopy = [cachedChannel copy];
INCREMENT_COUNTER
[channelCopy addItemsFromChannel:obj];
DECREMENT_COUNTER;
}
block(channelCopy, err);
}];
NSURL *imageUrl = [NSURL URLWithString:storyImageURL];
INCREMENT_COUNTER;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
thumbnailData = [NSData dataWithContentsOfURL:imageUrl];
dispatch_async(dispatch_get_main_queue(), ^{
thumbnail = [UIImage imageWithData:thumbnailData];
DECREMENT_COUNTER;
if (COUNTER_REACHED_ZERO)
CALL_ARCHIVE_METHOD_ON_CHANNEL OBJECT
});
});