【问题标题】:ASIHTTPRequest - data from cache always emptyASIHTTPRequest - 来自缓存的数据始终为空
【发布时间】:2011-06-25 13:50:26
【问题描述】:

我正在我的 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-method中,可以识别出缓存是成功的,但是我的request-object里面的数据是空的;我错过了什么?

- (void) requestFinished:(ASIHTTPRequest *)request {
   if ([request didUseCachedResponse]) {
       NSLog(@"cache, size: %i", [[request responseData] length]); // is always zero
       [self buildImageWithData:[request responseData]];
   }
   [...];
}

非常感谢!

编辑 1: 我的完整代码不起作用:第一次,我得到“未缓存”语句,从那时起,“缓存,大小: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下载小测试项目

【问题讨论】:

    标签: ios caching asihttprequest


    【解决方案1】:

    您能否设置断点,清除缓存(例如,删除您的应用程序),然后单步执行这段代码(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 中提供的数据。

    【讨论】:

    • @"接收数据的大小:%d 个字节", [[request responseData] length] => 给出 0 个字节;它采用第一个路径,因此它将 0 写入文件...
    • 如果您完全禁用缓存(即停止读取或写入缓存,因此它将始终从服务器获取),您的应用程序是否工作?看来您的问题可能不是缓存问题,而是服务器返回的数据有问题。
    • 感谢您的测试应用程序,这让它变得更加容易 - 我已经更新了我的答案!
    【解决方案2】:

    您的代码对我来说似乎是正确的。

    我唯一能想到的是,您的缓存中可能有一些“损坏”的数据,例如存储零长度数据的情况。您可以尝试只删除一次缓存或只使用一次ASIDoNotReadFromCacheCachePolicy 策略(以便“清除”缓存)。

    如果这没有帮助,我会在您的requestFinished: 中设置一个断点,然后从那里准确检查据称从缓存中检索数据时 ASIHTTP 中发生了什么。这比听起来容易。

    【讨论】:

    • 这就是我的观点;在 requestFinished:-method 中,数据已经是空的。不幸的是,ASIDoNotReadFromCacheCachePolicy 不起作用……我真的不知道这里出了什么问题……
    【解决方案3】:

    注释掉这个方法:

    (void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
    {
       [imageDataLoadedFromURL appendData:data];
    }
    

    【讨论】:

      【解决方案4】:

      试试这个,告诉我你得到了什么:

      - (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

      【讨论】:

      • %lu 是不可能的(编译器错误);我只能使用“%u”,结果也是 0。 didReceiveResponseHeaders 的更改没有任何后果; imageDataLoadedFromURL 是 NSMutableData...
      • 没有改变任何东西;另请参阅我更新的原始帖子;似乎写入缓存不起作用...
      • Size of received data: %d bytes 总是显示 0 ?您还没有使用更新的代码或您的真实图像是 0 字节
      • 我的真实图像是 0,因为我在缓存中找到了它(请参阅我的原始帖子的编辑)
      • 我的意思是你的服务器图像。Size of received data: %d bytes 总是显示 0 吗?
      【解决方案5】:

      我尝试运行您的应用。亚历山大的建议是对的。

      注释掉这个方法:

      (void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
      

      在注释掉这个方法时,调用的 requestDone 方法将具有整个请求内容,因此具有大小。

      【讨论】:

        猜你喜欢
        • 2017-05-07
        • 2014-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多