web-dev-qa-db-ja.com

UIWebViewデリゲートメソッドshouldStartLoadWithRequest:WKWebViewで同等ですか?

IOS 7+アプリ内にUIWebViewであるモジュールがあります。 htmlページは、カスタム形状のボタンを作成するjavascriptをロードします(Raphaeljsライブラリを使用)。 UIWebViewを使用して、デリゲートをselfに設定します。デリゲートメソッド_webView: shouldStartLoadWithRequest: navigationType:_は、カスタムボタンの1つが押されるたびに呼び出されます。リクエストはhtmlで処理されるのではなく、iOSコードで処理される必要があります。そこで、リクエストのスキームとして「inapp」を使用して、リクエスト規約(stackoverflowのどこかで読んでください)を使用しました。次に、ホストを確認し、適切なアクションを実行します。

このコードはiOS 7では正常に機能しますが、iOS 8ではWebビューが空白に見える(バグ?)ので、iOS 8デバイスにWKWebViewを使用することにしました。 Webビューは今ではうまく(そして驚くほど高速に)レンダリングされますが、私のボタンは効果がありません。

- (WKNaviation *)loadRequest:(NSURLRequest *)requestを使用してみましたが、呼び出されません。

UIWebViewデリゲートメソッド_webView: shouldStartLoadWithRequest: navigationType:_に直接相当するものが見つかりません。 WKWebViewでこれらのリクエストを処理する最良の方法は何ですか?

42
invalidArgument

説明を読み直すと、実際に知る必要があるのは、WKWebViewを使用してJavascript/Objective-Cブリッジを再実装する方法であるように見えます。

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プロトコルをView Controllerのヘッダーに含めます。

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

@end

WKWebViewを初期化するとき、スクリプトメッセージハンドラーで構成する必要があります。好きな名前を付けますが、私にとっては、アプリの名前を付けるのが理にかなっているようです。

    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:。これは、Webビューがメッセージを受信したときに起動するため、以前に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"});
13
SeanR

私は自分で良い説明を探していましたが、見つけられませんでした。私は私のアプリで次のものを使用しましたが、すべてが動作しているようです(Edit: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:が呼び出されることはもう確信できませんが)ライフサイクルのまったく同じポイント)、説明を読み直すと、実際に知っておく必要があるのは、WKWebViewを使用してJavascript/Objective-Cブリッジを再実装する方法であるように見えます。他の答えを見てください。

82
SeanR

元の質問に答えるには、webView:shouldStartLoadWithRequest:navigationType: UIWebViewのwebView:decidePolicyForNavigationAction:decisionHandler: WKWebViewで。これらのメソッドは、各要求(最初の要求を含む)が行われる前に呼び出され、それを許可/禁止する機能を提供します。

69
robnasby

次のメソッドを使用するだけで、それはWKNavigationDelegateの一部です

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

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

    decisionHandler(WKNavigationActionPolicyAllow);
}
28
Benzi Heler

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>
10

for Swift 4.2:(Yifei He何一非から取得)

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

        let url = navigationAction.request.url
        let urlStr = url?.absoluteString
        switch urlStr {
        case BASE_URL:
            //self.someFunc()
            decisionHandler(.cancel)
            break
        default:
            decisionHandler(.allow)
            break
        }

    }
3
ingconti

WKWebViewにObserverを追加できます

 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"];
}
0
ramzi shadid