У меня есть простое приложение, загружающее сайт, оптимизированный для iPhone, на UIWebView.
Проблема в том, что кеширование не работает:
[webView loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: url]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval: 60.0]];
Любые вещи, на которые есть ссылки на этой удаленной странице (css, изображения, внешние файлы javascript), никогда не кэшируются (запросы никогда не отправляют заголовок If-Modified-Since или что-либо еще для управления кешем).
Является ли это возможным? Похоже, что в обычном Cocoa WebView есть методы делегата, которые вызываются для каждого запроса ресурса и пост-загрузки (-didFinishLoadingFromDataSource:), которые вы могли бы использовать для сворачивания собственного кеширования ... но здесь это не похоже.
Вся моя страница (страница и связанные с ней ресурсы) сжата примерно на 89 КБ ... что медленнее по 3G в некоторых местах и даже хуже по EDGE. Входящие запросы, по крайней мере, указывают на то, что он принимает сжатие (accept-encoding=gzip, deflate), так что я полагаю, что это хорошо.
Я прочитал это исследование юи, который, кажется, указывает на то, что iPhone будет кэшировать 25 КБ на каждый элемент. Единственное, что упоминается, что несжатый более 25 КБ, это jquery (упакованный, но несжатый - это 30 КБ). Все остальное должно быть кешируемым. Никакой запрос на что-либо, на что имеется ссылка на выбранной странице, не запускает 304 на стороне сервера.
Это исследование yui было проведено почти год назад, и я предполагаю, что только с мобильным сафари.
Это использование UIWebView в родном приложении для iPhone.





Возможности кэширования iPhone ограничены по сравнению с обычным компьютером. Он ограничивает количество элементов кэша несжатый до 25 КБ.
Хорошая информация здесь: http://yuiblog.com/blog/2008/02/06/iphone-cacheability/
Вы всегда можете выполнить запросы вручную, хотя это будет сложно - и тогда вы сможете кэшировать вещи, сколько душе угодно. Создайте UIWebViewDelegate, который запускает запрос в webView:shouldStartLoadWithRequest:navigationType:, кэширует результат и использует loadHTMLString:baseURL: UIWebView для обновления представления.
Это будет некрасиво, и все будет работать не так гладко, как вам хотелось бы, но этого может быть достаточно для того, что вам нужно.
Как я вижу, одним из способов решения этой проблемы является
1) скачать HTML-код
2) сохраните его в строке
3) найдите в нем все внешние ссылки вроде
<img src = "img.gif" width = "..." height = "..." />
4) скачать их все
5) замените их встроенной версией в кодировке Base64
<img src = "data:image/gif;base64,R0lGODlhUAAPA...JADs= " width = "..." height = "..." />
6) наконец, сохраните полный HTML со встроенными изображениями, как хотите.
Лучший способ сделать это неправильно. Чувак, мы ищем здесь, по крайней мере, более удобное решение
@ eagle.dan.1349 почему это лучший способ сделать это неправильно? при отсутствии "чуть более удобного решения" это является самое удобное решение
эй, кто-нибудь подразумевает это решение? Это работает?
Теперь вы можете попробовать ASIWebPageRequest от All Seeing Interactive:
ASIWebPageRequest is a new experimental addition to the ASIHTTPRequest family. It can be used to download a complete webpage, including external resources like images and stylesheets, in a single request. Once a web page is downloaded, the request will parse the content, look for external resources, download them, and insert them directly into the html source using Data URIS. You can then take the response and put it directly into a UIWebView / WebView on Mac.
Я могу только посоветовать всем использовать отличную библиотеку Бена Копси для всех видов HTTP-операций.
ОБНОВИТЬ: Бен прекратил поддержку ASIHTTPRequest. Я больше не предлагаю его использовать.
Привет, @rage, ты можешь предложить какие-нибудь альтернативы ASIWebPageRequest?
AFNetworking довольно хорош. Также MKNetworking. Широкая публика еще не решила, какой из них станет следующим стандартом де-факто. Я не уверен, что какой-либо из них поддерживает загрузку полной веб-страницы.
Спасибо @rage. Я использую AFNetworking для своих вызовов API, но не для полной загрузки / кеширования веб-страницы. Я пишу приложение-контейнер, в котором размещается веб-приложение Backbone внутри UIWebview, и я ищу способы ускорить его загрузку.
От https://github.com/phonegap/phonegap-iphone/issues/148:
NSURLCache* cache = [NSURLCache sharedURLCache];
[cache setMemoryCapacity:4 * 1024 * 1024];
[cache setDiskCapacity:512*1024];
[NSURLRequest requestWithURL:appURL
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:10.0];
Я думаю ссылка не работает
Вы должны иметь возможность создать подкласс NSURLCache и заменить его на общий кэш, используемый UIWebView, как описано в этой статье «Какао с любовью»: Подстановка локальных данных для удаленных запросов UIWebView
Для другого подхода посмотрите Выпадающее автономное кеширование для UIWebView (и NSURLProtocol).
Гениально, хотя и весьма тревожно.