ASIHTTPRequest - данные из кеша всегда пустые

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

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

5 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам