以下是我的代码如何从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
答案 0 :(得分:2)
您可以使用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];
即使从缓存中获取图像,也会调用成功块。希望它有所帮助!
答案 1 :(得分:1)
默认使用缓存。要进行测试,请转到您可以访问图片的网址,然后删除该图片,然后重新加载,并且您会看到它已被缓存:D图像有时不会被缓存,如果它们是'大图像。
如果您想增加此缓存大小,请将其放入您的app delegate:
[[NSURLCache sharedURLCache] setMemoryCapacity:(20*1024*1024)];
[[NSURLCache sharedURLCache] setDiskCapacity:(200*1024*1024)];
编辑RE:评论:
如果您只想将图像下载一次到文档路径,那么测试图像是否已存在且应该下载的最佳方法可能是您可以创建的测试。例如,如果图像中已存在图像的最后一个路径组件(图像文件路径的最后一部分),则不要下载它,否则下载它。
编辑:进一步评论
在UIKit + AFNetworking / UIImageView + AFNetworking.h内部
/ ** 从指定的URL异步下载映像,并在请求完成后设置它。之前对接收器的任何图像请求都将被取消。 如果图像在本地缓存,则立即设置图像,否则将立即设置指定的占位符图像,然后在请求完成后设置远程图像。 默认情况下,URL请求的
Accept
标头字段值为" image / *",缓存策略为NSURLCacheStorageAllowed
,超时间隔为30秒,并且设置为不处理饼干。要以不同方式配置网址请求,请使用setImageWithURLRequest:placeholderImage:success:failure:
@param url用于图像请求的URL。 * /
- (void)setImageWithURL:(NSURL *)url;
这看起来与您正在寻找的内容完全相同
使用:
#import <AFNetworking/UIKit+AFNetworking.h>
并使用
NSURL *strURL = [NSURL URLWithString:@"http://www.example.com/image.jpg"];
[imageview setImageWithURL:strURL];
答案 2 :(得分:0)
我建议您使用此库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);
}
}];
}
}