ios - UIWebView open links in Safari

ID : 10043

viewed : 31

Tags : iosuiwebviewmobile-safariios

Top 5 Answer for ios - UIWebView open links in Safari

vote vote

98

Add this to the UIWebView delegate:

(edited to check for navigation type. you could also pass through file:// requests which would be relative links)

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {     if (navigationType == UIWebViewNavigationTypeLinkClicked ) {         [[UIApplication sharedApplication] openURL:[request URL]];         return NO;     }      return YES; } 

Swift Version:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {         if navigationType == UIWebViewNavigationType.LinkClicked {             UIApplication.sharedApplication().openURL(request.URL!)             return false         }         return true     } 

Swift 3 version:

func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {     if navigationType == UIWebViewNavigationType.linkClicked {         UIApplication.shared.openURL(request.url!)         return false     }     return true } 

Swift 4 version:

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 } 

Update

As openURL has been deprecated in 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; } 
vote vote

85

If anyone wonders, Drawnonward's solution would look like this in Swift:

func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {     if navigationType == UIWebViewNavigationType.LinkClicked {         UIApplication.sharedApplication().openURL(request.URL)         return false     }     return true } 
vote vote

79

One quick comment to user306253's answer: caution with this, when you try to load something in the UIWebView yourself (i.e. even from the code), this method will prevent it to happened.

What you can do to prevent this (thanks Wade) is:

if (inType == UIWebViewNavigationTypeLinkClicked) {     [[UIApplication sharedApplication] openURL:[inRequest URL]];     return NO; }  return YES; 

You might also want to handle the UIWebViewNavigationTypeFormSubmitted and UIWebViewNavigationTypeFormResubmitted types.

vote vote

70

The other answers have one problem: they rely on the action you do and not on the link itself to decide whether to load it in Safari or in webview.

Now sometimes this is exactly what you want, which is fine; but some other times, especially if you have anchor links in your page, you want really to open only external links in Safari, and not internal ones. In that case you should check the URL.host property of your request.

I use that piece of code to check whether I have a hostname in the URL that is being parsed, or if it is embedded 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;      } } 

You can of course adapt the regular expression to fit your needs.

vote vote

53

In Swift you can use the following code:

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

Make sure you check for the URL value and the navigationType.

Top 3 video Explaining ios - UIWebView open links in Safari

Related QUESTION?