Uiwebview Open Links in Safari

UIWebView open links in Safari

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

Open link in Safari from UIWebView

You will need to either grant permission to that specific domain in your info.plist :

<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>testdomain.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<true/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<true/>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
<key>NSRequiresCertificateTransparency</key>
<false/>
</dict>
</dict>
</dict>

This info in your plist basically sets up an exception in your app. It allows you to access the testdomain.com domain (insert whatever domain you are trying to access). It lets you access all of the subdomains and then sets a minimum TLS version to help ensure the site you are connecting to is the one you want.

Or you you can simply allow access to all http websites, which is not recommended.

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

This isn't recommended because it allows your app to access any http:// domain, which can be a security problem because it can make your app vulnerable to man-in-the-middle attacks.

Check out Apple's documentation for more info on this.
https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33

Open external link from UIWebView in Safari

You need to handle this in the UIWebView delegate method and check with the UIWebViewNavigationType.

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

if(navigationType == UIWebViewNavigationTypeLinkClicked){

[MAIN_APPLICATION_DELEGATE openURL:request.URL];
}
}

Open specific link in Safari from UIWebView

Here is how you can do it!

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

Open UIWebView Links In Safari

Using UIWebView:

Make sure your view controller conforms to UIWebViewDelegate and then implement this method in the controller:

class VideosViewController : UIViewController, UIWebViewDelegate {

@IBOutlet weak var webView : UIWebView!

override func viewDidLoad() {
super.viewDidLoad()

guard let url = URL(string: "http://example.com") else { return }

webView.delegate = self

let request = URLRequest(url: url)
webView.loadRequest(request)

}

func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {

if navigationType == .linkClicked {

guard let url = request.url else { return true }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
return false
}
return true
}
}


Using WKWebView:

Use a WKWebView instead of a UIWebView and make sure your controller conforms to the WKNavigationDelegate protocol. So your implementation would look something like the following:

class VideosViewController : UIViewController, WKNavigationDelegate {

var webView : WKWebView!

override func viewDidLoad() {
super.viewDidLoad()

guard let url = URL(string: "http://example.com") else { return }

webView = WKWebView(frame: self.view.frame)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.isUserInteractionEnabled = true
webView.navigationDelegate = self

self.view.addSubview(self.webView)

let request = URLRequest(url: url)
webView.load(request)

}


func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

// Check if a link was clicked
if navigationAction.navigationType == .linkActivated {

// Verify the url
guard let url = navigationAction.request.url else { return }
let shared = UIApplication.shared

// Check if opening in Safari is allowd
if shared.canOpenURL(url) {

// Ask the user if they would like to open link in Safari
let alert = UIAlertController(title: "Open link in Safari?", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (alert: UIAlertAction) -> Void in
// User wants to open in Safari
shared.open(url, options: [:], completionHandler: nil)
}))
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))

present(alert, animated: true, completion: nil)

}
decisionHandler(.cancel)
}
decisionHandler(.allow)
}
}

This way, when a user clicks a link in the web view, they will be prompted with an alert that will ask them whether or not they would like to open it in Safari, and if it is allowed, Safari will launch and the link will be opened.

How to open all links, besides some, in Safari with UIWebView?

You can store a list of allowed URLs and filter on the host name of the request URL. If the host matches one of the allowed URLs then return true to allow the URL to load in the web view. Otherwise use UIApplication.openURL() to open the URL in Safari.

For example:

let safeList = [ "paypal.com", "google.com" ]

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

if navigationType == UIWebViewNavigationType.LinkClicked {

if let host = request.URL?.host where safeList.contains(host) {
return true // Open in web view
}

UIApplication.sharedApplication().openURL(request.URL!)
return false
}

return true
}

WKWebView open links from certain domain in safari

You can implement WKNavigationDelegate, add the decidePolicyForNavigationAction method and check there the navigationType and requested url. I have used google.com below but you can just change it to your domain:

Xcode 8.3 • Swift 3.1 or later

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

let webView = WKWebView()

override func viewDidLoad() {
super.viewDidLoad()

webView.frame = view.bounds
webView.navigationDelegate = self

let url = URL(string: "https://www.google.com")!
let urlRequest = URLRequest(url: url)

webView.load(urlRequest)
webView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
view.addSubview(webView)
}

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if navigationAction.navigationType == .linkActivated {
if let url = navigationAction.request.url,
let host = url.host, !host.hasPrefix("www.google.com"),
UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
print(url)
print("Redirected to browser. No need to open it locally")
decisionHandler(.cancel)
return
} else {
print("Open it locally")
decisionHandler(.allow)
return
}
} else {
print("not a user click")
decisionHandler(.allow)
return
}
}
}


Related Topics



Leave a reply



Submit