我有一个非常简单的UIWebView,包含我的应用程序包中的内容。我想任何链接在web视图中打开Safari而不是在web视图。这可能吗?
当前回答
在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
}
}
确保检查了URL值和navigationType。
其他回答
将这个添加到UIWebView委托:
(经过编辑以检查导航类型。你也可以通过file:// requests传递相对链接)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
斯威夫特版本:
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版本:
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版本:
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
}
更新
由于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;
}
对user306253的回答的一个快速评论:小心,当你自己尝试在UIWebView中加载一些东西时(即即使从代码中加载),这个方法将防止它发生。
你能做什么来防止这种情况(感谢韦德):
if (inType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
你可能还想处理UIWebViewNavigationTypeFormSubmitted和UIWebViewNavigationTypeFormResubmitted类型。
如果有人想知道,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
}
其他答案有一个问题:它们依赖于你所做的操作,而不是链接本身来决定是在Safari中加载还是在webview中加载。
有时候这正是你想要的,这很好;但有些时候,特别是当你的页面中有锚点链接时,你想在Safari中只打开外部链接,而不是内部链接。在这种情况下,您应该检查URL。请求的主机属性。
我使用这段代码来检查正在解析的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;
}
}
当然,您可以调整正则表达式以满足您的需要。
不建议使用UIWebView和UIWebViewDelegate。你将不被允许将更新推送到Appstore。参考
使用WKWebView和WKNavigationDelegate
示例代码:
class YourClass: WKNavigationDelegate {
override public func viewDidLoad() {
super.viewDidLoad()
let webView = WKWebView()
webView.navigationDelegate = self
self.view.addaddSubview(webView)
}
public func webView(_ webView: WKWebView,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
}
public func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
self.webView.load(navigationAction.request)
decisionHandler(.allow)
}
}
推荐文章
- 架构i386的未定义符号:_OBJC_CLASS_$_SKPSMTPMessage",引用自:错误
- UILabel对齐文本到中心
- Objective-C中方法混合的危险是什么?
- 如何使用接口生成器创建的nib文件加载UIView
- iOS如何设置应用程序图标和启动图像
- 更改UITextField和UITextView光标/插入符颜色
- 'Project Name'是通过优化编译的——步进可能会表现得很奇怪;变量可能不可用
- 如何设置回退按钮文本在Swift
- 模拟器慢动作动画现在打开了吗?
- 如何为TableView创建NSIndexPath
- 滑动删除和“更多”按钮(就像iOS 7的邮件应用程序)
- 使UINavigationBar透明
- 如何改变推和弹出动画在一个基于导航的应用程序
- 删除/重置核心数据中的所有条目?
- setNeedsLayout vs. setNeedsUpdateConstraints和layoutIfNeeded vs. updateConstraintsIfNeeded