NSURLCache, обеспечивающий непоследовательные результаты на iOS5, казалось бы, случайным образом

Я просто потратил слишком много времени, крича свою голову в NSURLCache, поэтому я предлагаю этот совет, надеясь, что другие смогут избежать моей беды.

Все началось довольно разумно. Мой новый проект для приложений ориентирован только на iOS 5 и выше, поэтому я подумал, что могу использовать новую реализацию NSURLCache для всех моих потребностей в кэшировании. Я нуждался в специальном подклассе NSURLCache для обработки нескольких специальных задач, но все это, по-видимому, поддерживалось API. Быстрое чтение документации, и я уезжаю на гонки:

[NSURLCache setSharedURLCache:[[MyCustomCache alloc] initWithMemoryCapacity:8 * 1024 * 1024 //8mb 
                                                                    diskCapacity:32 * 1024 * 1024 // 32mb 
                                                                        diskPath:@"webcache.db"]];

Я считаю, что кеш-память размером 8 МБ прекрасна, и я верну ее с большим дисковым кешем, чтобы мы могли обслуживать больше наших больших изображений локально. Я подключаю остальную часть своего сетевого кода к использованию NSURLConnection (фактически, я использовал MKNetworkKit, но это оказалось неактуальным), и ожидайте отличных результатов от моего кэш. Разумеется, все запросы, которые должны быть кэшированы, покорно сохраняются в кеше, и ответы добросовестно летают быстро, когда они обслуживаются из кеша. Это регулярное производство Pirates of Penzance с такой большой нагрузкой, что я летаю в своем сетевом стеке.

Кроме того, что не складывается. Запросы, которые могут быть поданы из кеша, по-прежнему выходят из сети. За исключением случаев, когда это не так. Кажется совершенно случайным и прерывистым, действительно ли кеш используется для обслуживания запроса. Я отрываю свои волосы от разочарования и в буквальном смысле слова все стараюсь выяснить, что происходит. Я создаю тестовые приложения, устанавливаю точки останова повсюду, разрываю трассировку пакетов, читаю каждое слово в Интернете, которое упоминает NSURLCache, экспериментирует с заголовками кеш-контроля, комментирует код, обходит мой подкласс и даже прибегает к кропотливой трассировке через сборку для NSURLCache и ее друзей CFNetworking, чтобы попытаться понять, что таинственная логика лежит ниже. Я значительно улучшаю свои знания в области ARM и Objective-C, вызывая соглашения и немного разбираясь в низкоуровневой отладке, но нигде не узнаю, что происходит. Все это гораздо больше похоже на Iolanthe Nightmare Song, чем доброкачественная диктатура Пиратского короля, и я в значительной степени на грани того, чтобы выбросить все это.

Версия TL/DR: NSURLCache работает, но беспорядочно не возвращает кешированные результаты, даже если он доступен.

Ответ 1

В конце концов, я пробую другую перестановку всех битов, с которыми я играл. Я установил размер памяти и дискового кэша в 8 МБ.

И вот, вся странность уходит! Все, что должно быть кэшировано, сохраняется. И все, что должно происходить из кеша, обслуживается без сетевых запросов.

Кажется, что реализация NSURLCache в iOS5 еще не завершена. Он использует кеши дисков и памяти (в отличие от iOS4 и более ранних версий, которые только реализовали кеш в памяти), но на самом деле он не пропускает кеш памяти в кэш диска при пропуске запроса. Таким образом, это в основном слепая удача (ну, слепая удача зависит от вашей другой сети и использования кеша), является ли данный ответ в памяти или нет в нужный момент. Это, вероятно, полезно для уменьшения количества файлов флэш-памяти IO на устройстве, но безумно неприятно, если вы ожидаете рационального поведения в классе.

Итак, со смешной песней и веселым танцем я проверяю свое двухстрочное исправление и спешу в баре, в конце концов делюсь этими знаниями с SO (и отчет об ошибке Apple) в надежде, что никто другой не сможет повторите эту боль снова.

Мораль этой истории о горе: странные и злые вещи произойдут, если вы попытаетесь использовать NSURLCache на iOS5 с объемом диска, большим, чем объем памяти. Не делай этого. И избегайте врагов волшебных фей.

Ответ 2

FWIW здесь мое окончательное решение:

https://gist.github.com/3245415

для этого требуется использование FMDB, но результаты довольно хорошие.