ios UIWebView 在 Safari 中打开链接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2899699/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIWebView open links in Safari
提问by David Beck
I have a very simple UIWebView with content from my application bundle. I would like any links in the web view to open in Safari instead of in the web view. Is this possible?
我有一个非常简单的 UIWebView,其中包含我的应用程序包中的内容。我希望 web 视图中的任何链接在 Safari 中打开,而不是在 web 视图中打开。这可能吗?
回答by drawnonward
Add this to the UIWebView delegate:
将此添加到 UIWebView 委托:
(edited to check for navigation type. you could also pass through file://
requests which would be relative links)
(编辑以检查导航类型。您还可以传递file://
相对链接的请求)
- (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:
斯威夫特 3 版本:
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:
斯威夫特 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
}
Update
更新
As openURL
has been deprecated in iOS 10:
由于openURL
已被弃用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;
}
回答by DiegoFrings
If anyone wonders, Drawnonward's solution would look like this in Swift:
如果有人想知道,Drawnonward 的解决方案在Swift 中看起来像这样:
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == UIWebViewNavigationType.LinkClicked {
UIApplication.sharedApplication().openURL(request.URL)
return false
}
return true
}
回答by MonsieurDart
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.
对 user306253 的回答的一个快速评论:请注意这一点,当您尝试自己在 UIWebView 中加载某些内容时(即甚至从代码中),此方法将阻止它发生。
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.
您可能还想处理UIWebViewNavigationTypeFormSubmitted
和UIWebViewNavigationTypeFormResubmitted
类型。
回答by KPM
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.
其他答案有一个问题:它们依赖于您执行的操作而不是链接本身来决定是在 Safari 中还是在 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.
现在有时这正是您想要的,这很好;但有时,尤其是当您的页面中有锚链接时,您真的只想在 Safari 中打开外部链接,而不是内部链接。在这种情况下,您应该检查URL.host
您的请求的属性。
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:
我使用那段代码来检查正在解析的 URL 中是否有主机名,或者它是否是嵌入的 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.
您当然可以调整正则表达式以满足您的需要。
回答by Antoine
In Swift you can use the following code:
在 Swift 中,您可以使用以下代码:
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.
确保检查 URL 值和导航类型。
回答by danfordham
Here's the Xamarin iOS equivalent of drawnonward's answer.
这是与drawonward的答案等效的Xamarin iOS。
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;
}
}
回答by IanS
The accepted answer does not work.
接受的答案不起作用。
If your page loads URLs via Javascript, the navigationType
will be UIWebViewNavigationTypeOther
. Which, unfortunately, also includes background page loads such as analytics.
如果通过Javascript您的页面加载的网址,该navigationType
会UIWebViewNavigationTypeOther
。不幸的是,其中还包括后台页面加载,例如分析。
To detect page navigation, you need to compare the [request URL]
to the [request mainDocumentURL]
.
要检测页面导航,您需要将[request URL]
与[request mainDocumentURL]
.
This solution will work in all cases:
此解决方案适用于所有情况:
- (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;
}
}
回答by Nazmul Hasan
App rejection Note:
应用拒绝注意:
Finally UIWbView
is dead and Apple will not longer accept it.
终于UIWbView
死了,苹果不会再接受它。
Apple started sending email to all the App owner who are still using UIWebView
:
Apple 开始向所有仍在使用的 App 所有者发送电子邮件UIWebView
:
Deprecated API Usage - Apple will stop accepting submissions of apps that use UIWebView
APIs.
弃用的 API 使用 - Apple 将停止接受使用UIWebView
API的应用程序的提交。
Apple takes User Privacy very seriously and it is obvious that they won't allow insecure webview.
Apple 非常重视用户隐私,很明显他们不会允许不安全的 webview。
So do remove UIWebView from your app as soon as possible. don't use try to use UIWebView
in new created app and I Prefer to using WKWebView
if possible
因此,请尽快从您的应用程序中删除 UIWebView。不要尝试UIWebView
在新创建的应用程序中使用,WKWebView
如果可能,我更喜欢使用
ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of apps that use UIWebView APIs . See https://developer.apple.com/documentation/uikit/uiwebviewfor more information.
ITMS-90809:不推荐使用 API - Apple 将停止接受使用 UIWebView API 的应用程序的提交。有关更多信息,请参阅 https://developer.apple.com/documentation/uikit/uiwebview。
Example:
例子:
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")
}
}
回答by Michael Platt
In my case I want to make sure that absolutely everything in the web view opens Safari except the initial load and so I use...
在我的情况下,我想确保 web 视图中的所有内容都打开 Safari,除了初始加载,所以我使用...
- (BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if(inType != UIWebViewNavigationTypeOther) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}