我正在我的iPhone / iPad应用程序中下载图像 - 因为它们在大多数时间保持不变,我想将它们缓存在磁盘上:
ASIDownloadCache *cache = [ASIDownloadCache sharedCache];
[asiRequest setDownloadCache:cache];
[asiRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[asiRequest setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[asiRequest setSecondsToCache:60*60*24*30]; // Cache for 30 days
[asiRequest setDelegate:self]; // A delegate must be specified
[asiRequest setDidFinishSelector:@selector(requestFinished:)];
[asiRequest startAsynchronous];
在我的requestFinished方法中,我们认识到缓存是成功的,但是我的request-object中的数据是empyt;我错过了什么?
- (void) requestFinished:(ASIHTTPRequest *)request {
if ([request didUseCachedResponse]) {
NSLog(@"cache, size: %i", [[request responseData] length]); // is always zero
[self buildImageWithData:[request responseData]];
}
[...];
}
非常感谢!
编辑1:我的完整代码无法正常工作:第一次,我得到“not cached”语句,从那时起,“cache,size:0”...我有不明白为什么:(
- (void)viewDidLoad {
[super viewDidLoad];
for (int i = 0; i < 10; i++) {
asiRequest = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.myimageserver.com/myimage.jpg"]];
ASIDownloadCache *cache = [ASIDownloadCache sharedCache];
[asiRequest setDownloadCache:cache];
[asiRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[asiRequest setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[asiRequest setSecondsToCache:60*60*24*30]; // Cache for 30 days
[asiRequest setDelegate:self]; // A delegate must be specified
[asiRequest setDidFinishSelector:@selector(requestFinished:)];
[asiRequest startAsynchronous];
}
}
- (void) request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders {
self.imageDataLoadedFromURL = [NSMutableData data];
}
- (void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data {
[imageDataLoadedFromURL appendData:data];
}
- (void) requestFinished:(ASIHTTPRequest *)request {
if ([request didUseCachedResponse]) {
NSLog(@"cache, size: %i", [[request responseData] length]); // is always zero
} else {
NSLog(@"not cached");
}
}
编辑2:似乎缓存已包含0字节图像;所以这不是从缓存中读取而是写入它的问题......
编辑3 :您可以从http://tinyurl.com/68wuwj2下载小型测试项目
答案 0 :(得分:2)
您可以设置断点,清除缓存(例如删除您的应用),然后单步执行这段代码(ASIDownloadCache.m,第184行,方法storeResponseForRequest):
if ([request responseData]) {
[[request responseData] writeToFile:dataPath atomically:NO];
} else if ([request downloadDestinationPath] && ![[request downloadDestinationPath] isEqualToString:dataPath]) {
NSError *error = nil;
[[[[NSFileManager alloc] init] autorelease] copyItemAtPath:[request downloadDestinationPath] toPath:dataPath error:&error];
}
检查遵循的路径,并检查request.responseData。
的大小** 编辑 **
您的问题是您使用didReceiveData:
- (void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data {
[imageDataLoadedFromURL appendData:data];
}
引用asi http请求文档:
如果您需要将响应处理为 它进来(例如,你想要 使用流解析器来解析 在它还在的时候回应 已下载),请您的代表 实现请求:didReceiveData :(见 ASIHTTPRequestDelegate.h)。 请注意 当你这样做时,ASIHTTPRequest会 不填充responseData或写入 响应downloadDestinationPath - 你必须自己存储回复 如果你需要。
最后一句似乎也适用于缓存数据。
这可能是asihttprequest中的一个错误,实际上它不应该在这种情况下不将数据写入缓存,或者应该确保它正在写入有效数据 - 目前看起来它写的是无效的缓存条目。你需要在数据到达时处理它吗?如果不只是删除'didReceiveBytes'并且只使用requestFinished中request.responseData中提供的数据。
答案 1 :(得分:1)
您的代码对我来说似乎是正确的。
我唯一能想到的是你的缓存中可能有一些“损坏的”数据,比如存储了零腿数据。您可以尝试删除缓存一次或仅使用ASIDoNotReadFromCacheCachePolicy
策略一次(以便“清除”缓存)。
如果这没有帮助,我会在你的requestFinished:
中设置一个断点,并从那里检查ASIHTTP中发生的事件,当据称从缓存中检索到数据时。这比听起来容易。
答案 2 :(得分:1)
注释掉这种方法:
(void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
{
[imageDataLoadedFromURL appendData:data];
}
答案 3 :(得分:0)
尝试使用它并告诉我你得到了什么:
- (void) requestFinished:(ASIHTTPRequest *)request {
NSLog(@"Size of received data: %d bytes",[[request responseData] length]); //THIS LINE
if ([request didUseCachedResponse]) {
NSLog(@"cached");
} else {
NSLog(@"not cached");
}
}
然后尝试将此方法更改为:
- (void) request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders {
[self.imageDataLoadedFromURL setLength:0];
}
并确保您使用self.imageDataLoadedFromURL
作为NSMutableData
答案 4 :(得分:0)
我试过运行你的应用。亚历山大的建议是对的。
注释掉这种方法:
(void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
在注释掉这个方法时,被调用的requestDone方法将拥有整个请求内容,从而具有大小。