如何使用 AFNetworking 从缓存中显示 UIImageView 中的图像?
How to show Image in UIImageView from cache using AFNetworking?
这是我的代码,如何从 URL 下载图像并使用 AFNetworking 将其保存到文档目录中。
现在,我的问题是如果图像已经从 URL 下载,那么图像将从缓存中加载而不是重新下载。我想使用 AFNetworking 来执行此操作。我知道这个问题的解决方案在#import "UIKit+AFNetworking/UIKit+AFNetworking.h"
里面
如果有人知道如何提供帮助,请帮助我解决问题。
#import "ViewController.h"
#define URL @"https://upload.wikimedia.org/wikipedia/commons/e/ec/USA-NYC-American_Museum_of_Natural_History.JPG"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.progressBar.hidden = YES ;
self.lblProgressStatus.hidden = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)Action:(UIButton *)sender
{
self.progressBar.hidden = NO ;
self.lblProgressStatus.hidden = NO ;
self.ActionDownload.enabled = NO ;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *strURL = [NSURL URLWithString:URL];
NSURLRequest *request = [NSURLRequest requestWithURL:strURL];
NSProgress *progress;
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
}
completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
[self.progressBar setHidden:YES];
self.lblProgressStatus.text = @"Download completed" ;
NSLog(@"File downloaded to: %@", filePath);
NSString * strTemp = [NSString stringWithFormat:@"%@", filePath];
NSArray *components = [strTemp componentsSeparatedByString:@"/"];
id obj = [components lastObject];
NSLog(@"%@", obj);
NSString *docPath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
NSString *strFilePath = [NSString stringWithFormat:@"%@/%@",docPath, obj];
BOOL fileExists=[[NSFileManager defaultManager] fileExistsAtPath:strFilePath];
if (!fileExists)
{
NSLog(@"File Not Found");
}
else
{
UIImage * image = [UIImage imageWithContentsOfFile:strFilePath];
self.imageView.image = image ;
}
[progress removeObserver:self forKeyPath:@"fractionCompleted" context:NULL];
}];
[self.progressBar setProgressWithDownloadProgressOfTask:downloadTask animated:YES];
[downloadTask resume];
[progress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) options:NSKeyValueObservingOptionNew
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"fractionCompleted"])
{
NSProgress *progress = (NSProgress *)object;
int temp = progress.fractionCompleted * 100 ;
// NSLog(@"%d", temp);
NSString * strTemp = @"%";
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
self.lblProgressStatus.text = [NSString stringWithFormat:@"%d %@", temp, strTemp];
});
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
@end
默认使用缓存。要测试,请转到您有权访问的图像的 url,然后删除该图像,然后再次加载,您会看到它已被缓存 :D 如果图像是大图像,有时不会被缓存。
如果您想增加此缓存大小,请将其放入您的应用委托中:
[[NSURLCache sharedURLCache] setMemoryCapacity:(20*1024*1024)];
[[NSURLCache sharedURLCache] setDiskCapacity:(200*1024*1024)];
编辑回复:评论:
如果您只想将图像下载到文档路径一次,那么测试图像是否已经存在以及是否应下载的最佳方法可能是您可以创建一个测试。例如,如果图像的最后一个路径组件(图像文件路径的最后一部分)已经存在于您的文档中,请不要下载它,否则下载它。
编辑:进一步评论
Inside UIKit+AFNetworking/UIImageView+AFNetworking.h
/**
Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled.
If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished.
By default, URL requests have a Accept
header field value of "image / *", a cache policy of NSURLCacheStorageAllowed
and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, use setImageWithURLRequest:placeholderImage:success:failure:
@param url The URL used for the image request.
*/
- (void)setImageWithURL:(NSURL *)url;
这看起来与您正在寻找的完全一样
使用:
#import <AFNetworking/UIKit+AFNetworking.h>
并使用
NSURL *strURL = [NSURL URLWithString:@"http://www.example.com/image.jpg"];
[imageview setImageWithURL:strURL];
我推荐你使用这个库https://github.com/rs/SDWebImage
所以,你可以这样做:
- (void)loadImage:(NSURL *)url
{
__block UIImage *image = [[SDImageCache sharedImageCache] queryDiskCacheForKey:[url absoluteString]];
if(!image) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setTimeoutInterval: 30.0]; // Will timeout after 30 seconds
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data != nil && error == nil) {
image = [UIImage imageWithData:data];
NSData *pngData = UIImagePNGRepresentation(image);
[[SDImageCache sharedImageCache] storeImage:image imageData:pngData forKey:[url absoluteString] toDisk:YES];
}
else {
// There was an error, alert the user
NSLog(@"%s Error: %@", __func__, error);
}
}];
}
}
您可以使用UIImageView+AFNetworking
中定义的此方法下载图像:
[imageView setImageWithURL:[NSURL URLWithString:URL] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
if ([[extension lowercaseString] isEqualToString:@"png"]) {
[UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
} else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]) {
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
}
} failure:NULL];
即使从缓存中获取图像,也会调用成功块。希望对您有所帮助!
这是我的代码,如何从 URL 下载图像并使用 AFNetworking 将其保存到文档目录中。
现在,我的问题是如果图像已经从 URL 下载,那么图像将从缓存中加载而不是重新下载。我想使用 AFNetworking 来执行此操作。我知道这个问题的解决方案在#import "UIKit+AFNetworking/UIKit+AFNetworking.h"
如果有人知道如何提供帮助,请帮助我解决问题。
#import "ViewController.h"
#define URL @"https://upload.wikimedia.org/wikipedia/commons/e/ec/USA-NYC-American_Museum_of_Natural_History.JPG"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.progressBar.hidden = YES ;
self.lblProgressStatus.hidden = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)Action:(UIButton *)sender
{
self.progressBar.hidden = NO ;
self.lblProgressStatus.hidden = NO ;
self.ActionDownload.enabled = NO ;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *strURL = [NSURL URLWithString:URL];
NSURLRequest *request = [NSURLRequest requestWithURL:strURL];
NSProgress *progress;
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
}
completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
[self.progressBar setHidden:YES];
self.lblProgressStatus.text = @"Download completed" ;
NSLog(@"File downloaded to: %@", filePath);
NSString * strTemp = [NSString stringWithFormat:@"%@", filePath];
NSArray *components = [strTemp componentsSeparatedByString:@"/"];
id obj = [components lastObject];
NSLog(@"%@", obj);
NSString *docPath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
NSString *strFilePath = [NSString stringWithFormat:@"%@/%@",docPath, obj];
BOOL fileExists=[[NSFileManager defaultManager] fileExistsAtPath:strFilePath];
if (!fileExists)
{
NSLog(@"File Not Found");
}
else
{
UIImage * image = [UIImage imageWithContentsOfFile:strFilePath];
self.imageView.image = image ;
}
[progress removeObserver:self forKeyPath:@"fractionCompleted" context:NULL];
}];
[self.progressBar setProgressWithDownloadProgressOfTask:downloadTask animated:YES];
[downloadTask resume];
[progress addObserver:self
forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) options:NSKeyValueObservingOptionNew
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"fractionCompleted"])
{
NSProgress *progress = (NSProgress *)object;
int temp = progress.fractionCompleted * 100 ;
// NSLog(@"%d", temp);
NSString * strTemp = @"%";
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
self.lblProgressStatus.text = [NSString stringWithFormat:@"%d %@", temp, strTemp];
});
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
@end
默认使用缓存。要测试,请转到您有权访问的图像的 url,然后删除该图像,然后再次加载,您会看到它已被缓存 :D 如果图像是大图像,有时不会被缓存。
如果您想增加此缓存大小,请将其放入您的应用委托中:
[[NSURLCache sharedURLCache] setMemoryCapacity:(20*1024*1024)];
[[NSURLCache sharedURLCache] setDiskCapacity:(200*1024*1024)];
编辑回复:评论:
如果您只想将图像下载到文档路径一次,那么测试图像是否已经存在以及是否应下载的最佳方法可能是您可以创建一个测试。例如,如果图像的最后一个路径组件(图像文件路径的最后一部分)已经存在于您的文档中,请不要下载它,否则下载它。
编辑:进一步评论
Inside UIKit+AFNetworking/UIImageView+AFNetworking.h
/** Asynchronously downloads an image from the specified URL, and sets it once the request is finished. Any previous image request for the receiver will be cancelled. If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished. By default, URL requests have a
Accept
header field value of "image / *", a cache policy ofNSURLCacheStorageAllowed
and a timeout interval of 30 seconds, and are set not handle cookies. To configure URL requests differently, usesetImageWithURLRequest:placeholderImage:success:failure:
@param url The URL used for the image request. */
- (void)setImageWithURL:(NSURL *)url;
这看起来与您正在寻找的完全一样
使用:
#import <AFNetworking/UIKit+AFNetworking.h>
并使用
NSURL *strURL = [NSURL URLWithString:@"http://www.example.com/image.jpg"];
[imageview setImageWithURL:strURL];
我推荐你使用这个库https://github.com/rs/SDWebImage
所以,你可以这样做:
- (void)loadImage:(NSURL *)url
{
__block UIImage *image = [[SDImageCache sharedImageCache] queryDiskCacheForKey:[url absoluteString]];
if(!image) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setTimeoutInterval: 30.0]; // Will timeout after 30 seconds
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data != nil && error == nil) {
image = [UIImage imageWithData:data];
NSData *pngData = UIImagePNGRepresentation(image);
[[SDImageCache sharedImageCache] storeImage:image imageData:pngData forKey:[url absoluteString] toDisk:YES];
}
else {
// There was an error, alert the user
NSLog(@"%s Error: %@", __func__, error);
}
}];
}
}
您可以使用UIImageView+AFNetworking
中定义的此方法下载图像:
[imageView setImageWithURL:[NSURL URLWithString:URL] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
if ([[extension lowercaseString] isEqualToString:@"png"]) {
[UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
} else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]) {
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
}
} failure:NULL];
即使从缓存中获取图像,也会调用成功块。希望对您有所帮助!