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でこれらのリクエストを処理する最良の方法は何ですか?
説明を読み直すと、実際に知る必要があるのは、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"});
私は自分で良い説明を探していましたが、見つけられませんでした。私は私のアプリで次のものを使用しましたが、すべてが動作しているようです(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ブリッジを再実装する方法であるように見えます。他の答えを見てください。
元の質問に答えるには、webView:shouldStartLoadWithRequest:navigationType:
UIWebViewのwebView:decidePolicyForNavigationAction:decisionHandler:
WKWebViewで。これらのメソッドは、各要求(最初の要求を含む)が行われる前に呼び出され、それを許可/禁止する機能を提供します。
次のメソッドを使用するだけで、それはWKNavigationDelegateの一部です
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
NSString *url = [[request URL]absoluteString];
decisionHandler(WKNavigationActionPolicyAllow);
}
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>
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
}
}
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"];
}