私のiOSアプリケーション内には、UIWebViewがあります。
ここで、属性target = "_ blank"を持つすべてのリンクを、WebViewの内部ではなく、Safariの外部で開くようにします。
これどうやってするの?
Wedoのソリューションの問題は、すべてのリンクがSafariで開くことです。
2つの解決策:
1-target = "_ blank"の場合のObjective-CへのJavaScriptコールバック
問題を解決するには、すべてのリンクにJavaScriptを追加する必要があります。リンクに_blank属性があるかどうかを確認し、JavaScriptから目的のCコードを呼び出して実行します。
[[UIApplication sharedApplication] openURL:myUrl];
個人的には、このソリューションは多くのコード、コールバック、複雑さ、そして少し難しいので、好きではありません...
2-URLパラメータを確認しています
HTMLコードにアクセスできる場合(両方のソリューションでHTMLにアクセスする必要があることに注意してください)、target = "_ blank"を削除し、パラメーター?openInSafari = trueを追加することをお勧めします。
UIWebViewDelegateで、次のコードを追加します。
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSURL *url = [request URL];
NSDictionary *param = [url queryParameters];
NSString *openIsSafari = [param objectForKey:@"openInSafari"];
if ( openIsSafari!= nil && ([openIsSafari isEqualToString:@"true"] || [openIsSafari isEqualToString:@"1"])){
[[UIApplication sharedApplication] openURL:url];
return NO;
}
}
return YES;
}
このソリューションの良い(悪い?)ポイントは、リンクxレベルが深い場合でも、サファリブラウザへのリンクを開くことができるということです
<a href="http://www.google.com?openInSafari=true">Google in Safari</a>
常にURL(http、https ...)にプロトコルを追加してください
マーティンマガキアンへの称賛!以下は、spankmaster79の提案に基づく変更です。
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest: (NSURLRequest *)request navigationType: (UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSURL *url = [request URL];
NSString *param = [url query];
if ([param rangeOfString: @"openInSafari=true"].location != NSNotFound){
[[UIApplication sharedApplication] openURL: url];
return NO;
}
}
return YES;
}
これを試して。
UIApplication *app = [UIApplication sharedApplication];
NSURL *url = navigationAction.request.URL;
if (!navigationAction.targetFrame) {
if ([app canOpenURL:url]) {
[app openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
if ([url.scheme isEqualToString:@"mailto"])
{
if ([app canOpenURL:url])
{
[app openURL:url];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
decisionHandler(WKNavigationActionPolicyAllow);
私は同じ質問をしましたが、残念ながらこれらの答えは私を完全に間違った非常に複雑な方法で引き起こしました。実際、この質問に対する答えは「WebViewPolicyDelegateProtocolを使用する必要がある」という単純なものです。
ビューコントローラ実装の-viewDidLoadで、次のように記述します。
[myWebView setPolicyDelegate:self];
ビューコントローラクラスインターフェイスで、次の2つの項目を追加する必要があります。
- (void)webView:(WebView *)webView
decidePolicyForNavigationAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id<WebPolicyDecisionListener>)listener;
- (void)webView:(WebView *)webView
decidePolicyForNewWindowAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
newFrameName:(NSString *)frameName
decisionListener:(id<WebPolicyDecisionListener>)listener;
そして、それらを次のように簡単に実装します。
- (void)webView:(WebView *)webView
decidePolicyForNavigationAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id<WebPolicyDecisionListener>)listener {
// just the default behavior, though you're free to add any url filtering you like...
[listener use];
}
- (void)webView:(WebView *)webView
decidePolicyForNewWindowAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
newFrameName:(NSString *)frameName
decisionListener:(id<WebPolicyDecisionListener>)listener {
// frameName is your "target" parameter value
if([frameName isEqualToString:@"_blank"]) {
[[NSWorkSpace sharedWorkSpace] loadURL:[request URL]];
} else {
[listener use];
}
}
Apple docs も参照してください。
私はプロジェクトでこの方法を使用しました。フレームセットはルートHTMLで使用され、WebViewにロードされます。別の既存のフレームを指すすべてのクロスリンクは2番目のメッセージ呼び出しを引き起こさないため、ここでは新しい(外部)ターゲットのみが処理されます。私にとっては問題ありません。