Tôi có một UIWebView rất đơn giản với nội dung từ gói ứng dụng của mình. Tôi muốn bất kỳ liên kết nào trong chế độ xem web sẽ mở trong Safari thay vì trong chế độ xem web. Điều này có thể không?
Tôi có một UIWebView rất đơn giản với nội dung từ gói ứng dụng của mình. Tôi muốn bất kỳ liên kết nào trong chế độ xem web sẽ mở trong Safari thay vì trong chế độ xem web. Điều này có thể không?
Câu trả lời:
Thêm phần này vào đại biểu UIWebView:
(được chỉnh sửa để kiểm tra loại điều hướng. Bạn cũng có thể chuyển qua file://
các yêu cầu có liên kết tương đối)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
Phiên bản Swift:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL!)
return false
}
return true
}
Phiên bản Swift 3:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.linkClicked {
UIApplication.shared.openURL(request.url!)
return false
}
return true
}
Phiên bản Swift 4:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
guard let url = request.url, navigationType == .linkClicked else { return true }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return false
}
Cập nhật
Như openURL
đã bị phản đối trong iOS 10:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
UIApplication *application = [UIApplication sharedApplication];
[application openURL:[request URL] options:@{} completionHandler:nil];
return NO;
}
return YES;
}
switch
thích hợp hơn cho các loại enum
Nếu có ai thắc mắc, giải pháp của Drawnonward sẽ giống như thế này trong Swift :
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL)
return false
}
return true
}
UIWebViewDelegate
Một nhận xét nhanh cho câu trả lời của người dùng 306253: hãy cẩn thận với điều này, khi bạn cố gắng tự tải một cái gì đó trong UIWebView (tức là ngay cả từ mã), phương pháp này sẽ ngăn nó xảy ra.
Những gì bạn có thể làm để ngăn chặn điều này (cảm ơn Wade) là:
if (inType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
Bạn cũng có thể muốn xử lý UIWebViewNavigationTypeFormSubmitted
và UIWebViewNavigationTypeFormResubmitted
các loại.
Các câu trả lời khác có một vấn đề: họ dựa vào hành động bạn làm chứ không dựa vào chính liên kết để quyết định tải nó trong Safari hay trong webview.
Bây giờ đôi khi đây là chính xác những gì bạn muốn, điều đó là tốt; nhưng một số lần khác, đặc biệt nếu bạn có các liên kết neo trong trang của mình, bạn thực sự muốn chỉ mở các liên kết bên ngoài trong Safari chứ không phải các liên kết nội bộ. Trong trường hợp đó bạn nên kiểm tra URL.host
tài sản của yêu cầu của bạn.
Tôi sử dụng đoạn mã đó để kiểm tra xem tôi có tên máy chủ trong URL đang được phân tích cú pháp hay nếu nó được nhúng html:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
static NSString *regexp = @"^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9])[.])+([A-Za-z]|[A-Za-z][A-Za-z0-9-]*[A-Za-z0-9])$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regexp];
if ([predicate evaluateWithObject:request.URL.host]) {
[[UIApplication sharedApplication] openURL:request.URL];
return NO;
} else {
return YES;
}
}
Tất nhiên bạn có thể điều chỉnh biểu thức chính quy để phù hợp với nhu cầu của bạn.
if (request.URL?.scheme != "file")
Trong Swift, bạn có thể sử dụng mã sau:
extension YourViewController: UIWebViewDelegate {
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
if let url = request.url, navigationType == UIWebView.NavigationType.linkClicked {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return false
}
return true
}
}
Đảm bảo bạn kiểm tra giá trị URL và loại điều hướng.
Đây là Xamarin iOS tương đương với câu trả lời của drawonward.
class WebviewDelegate : UIWebViewDelegate {
public override bool ShouldStartLoad (UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType) {
if (navigationType == UIWebViewNavigationType.LinkClicked) {
UIApplication.SharedApplication.OpenUrl (request.Url);
return false;
}
return true;
}
}
Câu trả lời được chấp nhận không hoạt động.
Nếu trang của bạn tải URL thông qua Javascript, thì navigationType
sẽ như vậy UIWebViewNavigationTypeOther
. Thật không may, cũng bao gồm tải trang nền như phân tích.
Để phát hiện điều hướng trang, bạn cần so sánh [request URL]
với [request mainDocumentURL]
.
Giải pháp này sẽ hoạt động trong mọi trường hợp:
- (BOOL)webView:(UIWebView *)view shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)type
{
if ([[request URL] isEqual:[request mainDocumentURL]])
{
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
else
{
return YES;
}
}
Từ chối ứng dụng Lưu ý:
Cuối cùng UIWbView
là chết và Apple sẽ không chấp nhận nó nữa.
Apple bắt đầu gửi email đến tất cả chủ sở hữu Ứng dụng vẫn đang sử dụng UIWebView
:
Sử dụng API không dùng nữa - Apple sẽ ngừng chấp nhận việc gửi các ứng dụng sử dụng UIWebView
API.
Apple rất coi trọng Quyền riêng tư của Người dùng và rõ ràng là họ sẽ không cho phép xem web không an toàn .
Vì vậy, hãy xóa UIWebView khỏi ứng dụng của bạn càng sớm càng tốt. không sử dụng thử sử dụng UIWebView
trong ứng dụng mới được tạo và tôi thích sử dụng WKWebView
nếu có thể
ITMS-90809: Sử dụng API không dùng nữa - Apple sẽ ngừng chấp nhận việc gửi các ứng dụng sử dụng API UIWebView. Xem https://developer.apple.com/documentation/uikit/uiwebview để biết thêm thông tin.
Thí dụ:
import UIKit
import WebKit
class WebInfoController: UIViewController,WKNavigationDelegate {
var webView : WKWebView = {
var webview = WKWebView()
return webview
}()
var _fileName : String!
override func viewDidLoad() {
self.view.addSubview(webView)
webView.fillSuperview()
let url = Bundle.main.url(forResource: _fileName, withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
webView.load(request)
}
func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
print(error.localizedDescription)
}
func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
print("Strat to load")
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
print("finish to load")
}
}
Trong trường hợp của tôi, tôi muốn đảm bảo rằng tất cả mọi thứ trong chế độ xem web sẽ mở Safari ngoại trừ tải ban đầu và vì vậy tôi sử dụng ...
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if(inType != UIWebViewNavigationTypeOther) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}