ASIHTTPRequest - данные из кеша всегда пустые - PullRequest
4 голосов
/ 25 июня 2011

Я загружаю изображения в своем приложении для 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 признается, что кэширование прошло успешно, но данные в моем объекте запроса - empyt; что мне не хватает?

- (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-байтовое изображение; так что проблема не в чтении из кэширования, а в записи в него ...

enter image description here

РЕДАКТИРОВАТЬ 3: Вы можете загрузить небольшой тестовый проект с http://tinyurl.com/68wuwj2

Ответы [ 5 ]

2 голосов
/ 28 июня 2011

Можете ли вы установить точку останова, очистить кеш (например, удалить свое приложение), а затем пройти через этот бит кода (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.

** EDIT **

Ваша проблема заключается в использовании didReceiveData:

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

Чтобы процитировать документацию asi http-запроса:

Если вам нужно обработать ответ по мере его поступления (например, вы хотите использовать потоковый анализатор для анализа ответа, пока он ещезагружается), попросите делегата реализовать запрос: didReceiveData: (см. ASIHTTPRequestDelegate.h). Обратите внимание, что при этом ASIHTTPRequest не будет заполнять responseData или записывать ответ для downloadDestinationPath - вы должны сохранить ответ самостоятельно, если вам нужно.

Похоже, последнее предложениетакже применимо к кешированию данных.

Это, вероятно, ошибка в asihttprequest, на самом деле она не должна либо записывать данные в кеш в этом случае, либо должна удостовериться, что она записывает правильные данные - в настоящее время похоже, что она пишет неверныезапись в кеш.Вам нужно обрабатывать данные по мере их поступления?Если нет, просто удалите «didReceiveBytes» и используйте только те данные, которые указаны в request.responseData в requestFinished.

1 голос
/ 30 ноября 2011

Закомментируйте этот метод:

(void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
{
   [imageDataLoadedFromURL appendData:data];
}
1 голос
/ 25 июня 2011

Ваш код мне кажется правильным.

Единственное, о чем я могу подумать, это то, что у вас могут быть некоторые "поврежденные" данные в вашем кеше, как в случае, если данные нулевой длины были сохранены.Вы можете попытаться удалить кэш только один раз или использовать политику ASIDoNotReadFromCacheCachePolicy только один раз (чтобы «очистить» кэш).

Если это не поможет, я бы поставил точку останова в вашем requestFinished: и оттуда проверьте, что именно произошло в ASIHTTP, когда данные якобы были извлечены из кэша.Это проще, чем кажется.

0 голосов
/ 28 февраля 2012

Я попытался запустить ваше приложение.Предложение Александра верно.

Закомментируйте этот метод:

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

При комментировании этого метода вызываемый метод requestDone будет иметь все содержимое запроса и, следовательно, размер.

0 голосов
/ 28 июня 2011

Попробуйте использовать это и скажите мне, что вы получаете:

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

...