UIWebView 加載 HTML 內容,點擊其中的超鏈接(如 YouTube 鏈接)希望在 Safari 或原生 App 中打開,而非在 WebView 內部跳轉。
設置 delegate 並實現 webView:shouldStartLoadWithRequest:navigationType: 方法。
// ViewController.h
@interface ViewController : UIViewController <UIWebViewDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end
// ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.webView.delegate = self;
// 加載包含鏈接的 HTML 字符串
NSString *html = @"Click here to watch.";
[self.webView loadHTMLString:html baseURL:nil];
}
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSURL *url = request.URL;
// 使用共享應用打開(Safari 或 Universal Links 對應 App)
[[UIApplication sharedApplication] openURL:url
options:@{} completionHandler:nil];
return NO; // 阻止 WebView 內部加載
}
return YES; // 允許其他加載(如初始 HTML、圖片資源)
}
navigationType == UIWebViewNavigationTypeLinkClicked 精確識別用戶點擊超鏈接,過濾掉 UIWebViewNavigationTypeOther(JS 跳轉)、FormSubmitted、Reload 等。NO 取消 WebView 加載,YES 允許繼續。openURL:options:completionHandler: (iOS 10+) 替代舊版 openURL:,支持 Universal Links 自動跳轉對應 App。UIWebView 自 iOS 12 棄用,iOS 17 完全移除。新項目請使用 WKWebView:
// WKWebView 同樣需實現 WKNavigationDelegate
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
[[UIApplication sharedApplication] openURL:navigationAction.request.URL
options:@{} completionHandler:nil];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
navigationType 可能為 Other,需額外判斷 request.URL.scheme 是否為 http/https。webView.dataDetectorTypes = UIDataDetectorTypeLink 可自動識別純文本 URL 但無法攔截點擊事件。apple-app-site-association 並開啟 Associated Domains。正確攔截鏈接點擊並外部打開,是 WebView 混合開發的基礎技能,遷移 WKWebView 刻不容緩。