Можете ли вы перехватить 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