Можете ли вы перехватить NSURLRequests в UIWebView, не нарушая кнопку "Назад"?
У меня возникли проблемы с загрузкой пользовательского HTML в мой UIWebView
без нарушения его метода goBack
.
Что работает
Я перехватываю URL-запросы моего UIWebView
, чтобы загрузить пользовательский HTML. У меня есть контроль над всем HTML, поэтому у меня есть специальные приложения, которые используют пользовательскую схему (т.е. myapp://arg1/?arg2=val
), которую я могу проанализировать в webView:shouldStartLoadWithRequest:navigationType:
. Я решаю, какой HTML я действительно хочу загрузить, и вызовите loadHTMLString:baseURL
и верните NO
, чтобы отменить исходный запрос.
Что не работает
Вышеизложенное отлично работает. Проблема в том, что я хочу использовать метод UIWebView's
goBack
, а loadRequest:
- единственный метод UIWebView
, который добавляет его в стек истории.
У меня есть несколько идей, но я не уверен, какие из них возможны и как их решать. Главное, что мне нужно вернуть YES
в webView:shouldStartLoadWithRequest:navigationType
, и мне нужно использовать метод UIWebView
loadRequest
.
Идея 1: Изменить NSURLRequest/Response:
Могу ли я подклассировать NSURLRequest, чтобы (когда UIWebView делает запрос), он фактически не делает HTTP-запрос и возвращает NSURLResponse с моим HTML-кодом? Или, возможно, изменить/подкласс/добавить метод категории в NSURLResponse? Мне нравится идея, что это реальный запрос, но я беспокоюсь о частных API и отказывается от App Store.
Идея 2: обращение к настраиваемому URL-протоколу
Зарегистрируйте настраиваемый протокол URL, чтобы приложение отвечало на него, и я могу вернуть ему законный запрос NSURLResponse (заполненный моим пользовательским HTML.)
Идея 3: Окуните кеш Создайте запрос с помощью этой политики кэша NSURLRequestReturnCacheDataDontLoad
, а затем каким-то образом получите мой HTML-код между веб-браузером и кешем?
Или, может быть, я полностью ошибаюсь?
Ответы
Ответ 1
Я бы рекомендовал против любого из вышеуказанных подходов.
Я получил # 3, но это было очень, очень хрупко и трудно отлаживать. (Например, Apple уничтожает и воссоздает NSURLRequests
, поэтому вы не можете просто подклассифицировать NSURLRequest и ожидать, чтобы пройти через последующий ответ.)
Это стало намного проще для моей собственной истории предыстории и обратите внимание на то, какую страницу загружать и прокручивать позицию (смещение по вертикальному экрану).
Ответ 2
Есть еще один действительно умный подход, который я только что тестировал: вместо того, чтобы переделывать код NSURLCache
или переписывать весь код истории навигации, просто создайте пользовательский NSURLProtocol
, который используется стандартным NSURLConnection
всякий раз, когда HTTP запрос сделан. Там вы создаете свой собственный NSURLRequest
для загрузки данных и можете проверять тип MIME, изменять содержимое запроса или кэшировать данные на диск, как вам будет угодно. Эта идея получила любезность Роба Напира:
http://robnapier.net/blog/offline-uiwebview-nsurlprotocol-588
Его код теперь также находится на GitHub:
https://github.com/rnapier/RNCachingURLProtocol
Ответ 3
Сначала я попытался пройти маршрут №3. Возможно, "Подстановка локальных данных для удаленных запросов UIWebView" на Cocoa с любовью поможет вам.