How can I open an external link in Safari not the app's UIWebView?
If the links you want to open in safari all contain a common string, you can use the next piece of code.
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
// Intercept the external http requests and forward to Safari.app
// Otherwise forward to the PhoneGap WebView
if ([[url scheme] isEqualToString:@"SCHEME"]) {
[[UIApplication sharedApplication] openURL:url];
return NO;
}
else {
return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
}
}
This code placed in the AppDelegate.m
will open all URL that use the specified SCHEME in Safari.
I'm afraid that is all I could come up with.
Hope this helps
UPDATE :
The code should be placed in the MainViewControler, at least for cordova 2.2.0.
The method is initially commented. I had to use it to redirect Google maps links :
NSRange isGoogleMaps = [[url absoluteString] rangeOfString:@"maps.google.com" options:NSCaseInsensitiveSearch];
NSRange isGoogleTerms = [[url absoluteString] rangeOfString:@"terms_maps.html" options:NSCaseInsensitiveSearch];
if(isGoogleMaps.location != NSNotFound || isGoogleTerms.location != NSNotFound ) {
[[UIApplication sharedApplication] openURL:url];
return NO;
}
else
return [super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
How to open external link from UIWebView not in my App, but in Safari? SWIFT
@Leo Dabus thanks a lot for this hint, but I guess I have a better solution:
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked{
UIApplication.sharedApplication().openURL(request.URL!)
return false
}
return true
}
this one works perfect.
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];
}
}
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
}
}
}
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
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;
}
Related Topics
Es6 Object Destructuring Default Parameters
JavaScript Promises - Reject VS. Throw
Should I Use Window.Navigate or Document.Location in JavaScript
How to Pass Along Variables with Xmlhttprequest
Browsers Automatically Evaluate Hex or Hsl Colors to Rgb When Setting via Element.Style.Background
Getelementsbyclassname to Change the Style of Elements When Event Occurs
Safari in iOS8 Is Scrolling Screen When Fixed Elements Get Focus
Tool for Checking Unused CSS Selectors
Good "Background-Size: Cover" Fallbacks/Shims/Tricks for Cross-Browser Compatibility on Divs
IE8 V8 Not Changing Class for a Dom Element Despite Js Function Changing the Element Attribute
React 'Cannot Read Property of Undefined' When Using Map
How to Get First and Last Day of the Current Week in JavaScript
Detecting the Onload Event of a Window Opened with Window.Open
Convert Special Characters to HTML in JavaScript
Parsing Iso 8601 Date in JavaScript