Open Links in Safari Instead of Uiwebview

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 links in Safari instead of UIWebVIew?

Have you set the delegate of the UIWebView to your UIViewController? There's nothing obviously wrong with your code as far as I can see, so it's likely to be something small like that.

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
}

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 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 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 can I force any links clicked within a WebView to open in Safari?

This is done essentially the same way in Swift as in Obj-C:

First, declare that your view controller conforms to UIWebViewDelegate

class MyViewController: UIWebViewDelegate

Then implement webViewShouldStartLoadingWithRequest:navigationType: in your View Controller:

// Swift 1 & 2
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
switch navigationType {
case .LinkClicked:
// Open links in Safari
UIApplication.sharedApplication().openURL(request.URL)
return false
default:
// Handle other navigation types...
return true
}
}

// Swift 3
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
switch navigationType {
case .linkClicked:
// Open links in Safari
guard let url = request.url else { return true }

if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
// openURL(_:) is deprecated in iOS 10+.
UIApplication.shared.openURL(url)
}
return false
default:
// Handle other navigation types...
return true
}
}

Finally, set your UIWebView's delegate, e.g., in viewDidLoad or in your Storyboard:

webView.delegate = self


Related Topics



Leave a reply



Submit