Подтвердить что ты не робот

Метод делегата UIWebView долженStartLoadWithRequest: эквивалент в WKWebView?

У меня есть модуль внутри моего приложения iOS 7+, которое является UIWebView. На странице html загружается javascript, который создает пользовательские кнопки (используя библиотеку Raphaeljs). С помощью UIWebView я устанавливаю делегат самостоятельно. Метод делегата webView: shouldStartLoadWithRequest: navigationType: вызывается каждый раз при нажатии одной из моих пользовательских кнопок. Запросы не должны обрабатываться html, а скорее кодом iOS. Поэтому я использовал соглашение о запросе (читал где-то здесь в stackoverflow), используя "inapp" в качестве схемы моих запросов. Затем я проверяю хост и выполняю соответствующие действия.

Этот код отлично работает на iOS 7. Но веб-представления отображаются на iOS 8 (ошибка?), поэтому я решил использовать WKWebView для iOS 8 устройств. Теперь веб-представления отображают прекрасный (и удивительно быстрый!), Но мои кнопки не действуют.

Я пытался использовать - (WKNaviation *)loadRequest:(NSURLRequest *)request, но он не вызывался.

Я не могу найти прямой эквивалент метода делегата UIWebView webView: shouldStartLoadWithRequest: navigationType:. Каков наилучший способ обработки этих запросов с помощью WKWebView?

4b9b3361

Ответ 1

Повторное чтение вашего описания похоже на то, что вам нужно знать о том, как переопределить мост Javascript/ Objective-C с помощью WKWebView.

Я только что сделал это сам, следуя учебному пособию http://tetontech.wordpress.com/2014/07/17/objective-c-wkwebview-to-javascript-and-back/ и информации на http://nshipster.com/wkwebkit/

WKWebView имеет встроенный способ связи между Javascript и Objective-C/Swift: WKScriptMessageHandler.

Во-первых, включите заголовки WebKit и WKScriptMessageHandler в свой заголовок контроллера просмотра:

#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface ViewController : UIViewController <WKScriptMessageHandler>

@end

При инициализации вашего WKWebView вам необходимо настроить его с помощью обработчика сообщения script. Назовите его, как хотите, но для меня это похоже на то, что его имя для вашего приложения имеет смысл.

    WKWebViewConfiguration *theConfiguration = 
          [[WKWebViewConfiguration alloc] init];
    [theConfiguration.userContentController 
          addScriptMessageHandler:self name:@"myApp"];

    _theWebView = [[WKWebView alloc] initWithFrame:self.view.frame 
                      configuration:theConfiguration];
    [_theWebView loadRequest:request];
    [self.view addSubview:_theWebView];

Теперь реализуем userContentController:didReceiveScriptMessage:. Это срабатывает, когда ваш веб-просмотр получает сообщение, поэтому он выполняет работу, которую вы ранее делали с помощью webView:shouldStartLoadWithRequest:navigationType:.

- (void)userContentController:(WKUserContentController *)userContentController 
                        didReceiveScriptMessage:(WKScriptMessage *)message {
    NSDictionary *sentData = (NSDictionary *)message.body;
    NSString *messageString = sentData[@"message"];
    NSLog(@"Message received: %@", messageString);
}

Теперь вы готовы получать сообщения от Javascript. Вызов функции, которую вы должны добавить в свой Javascript, таков:

window.webkit.messageHandlers.myApp.postMessage({"message":"Hello there"});

Ответ 2

Чтобы ответить на исходный вопрос, эквивалент webView:shouldStartLoadWithRequest:navigationType: в UIWebView webView:decidePolicyForNavigationAction:decisionHandler: в WKWebView. Эти методы вызывается перед каждым запросом (включая исходный запрос) и предоставляют возможность разрешить/запретить его.

Ответ 3

Я сам искал хорошее объяснение, но не нашел его. Я использовал следующее в своем приложении, и все, кажется, работает (Изменить: обновлено на основе комментария ccoroom):

UIWebViewDelegate     - webView:shouldStartLoadWithRequest:navigationType:
WKNavigationDelegate  - webView:decidePolicyForNavigationAction:decisionHandler:

Здесь другие методы UIWebViewDelegate:

UIWebViewDelegate     - webViewDidStartLoad:
WKNavigationDelegate  - webView:didCommitNavigation:

UIWebViewDelegate     - webViewDidFinishLoad:
WKNavigationDelegate  - webView:didFinishNavigation:

UIWebViewDelegate     - webView:didFailLoadWithError:
WKNavigationDelegate  - webView:didFailNavigation:withError:
                      - webView:didFailProvisionalNavigation:withError:

Мне бы хотелось, чтобы кто-то подтвердил это для меня, хотя.

Изменить: Собственно, я ответил на вопрос, который у вас был в названии (хотя я больше не уверен, что webView:didCommitNavigation: вызывается в той же точке жизненного цикла), но повторное чтение вашего описания выглядит так, как вам нужно знать о том, как переопределить мост Javascript/Objective-C с помощью WKWebView. Так что посмотрите на мой другой ответ.

Ответ 4

Просто используйте следующий метод, это часть WKNavigationDelegate

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURLRequest *request = navigationAction.request;
    NSString *url = [[request URL]absoluteString];

    decisionHandler(WKNavigationActionPolicyAllow);
}

Ответ 5

В Swift вы можете сделать что-то вроде этого:

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {

    switch navigationAction.request.URLString {
    case "http://action.is.needed/some-action":
        self.someFunc()
        decisionHandler(.Cancel)
        break
    default:
        decisionHandler(.Allow)
        break
    }

}

И это ссылка на веб-странице:

<a href="http://action.is.needed/some-action">Hello world!</a>

Ответ 6

Вы можете добавить Observer для своего WKWebView

 static void* keyValueObservingContext = &keyValueObservingContext;

[webView addObserver:self forKeyPath:@"URL" options:0 context:keyValueObservingContext];


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 {

if ([keyPath isEqualToString:@"URL"]){
// do something
  }
}

Не забудьте удалить его в viewWillDisappear

-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[webView removeObserver:self forKeyPath:@"URL"];
}