WKWebView 在 safari 中打开来自某个域的链接
Posted
技术标签:
【中文标题】WKWebView 在 safari 中打开来自某个域的链接【英文标题】:WKWebView open links from certain domain in safari 【发布时间】:2016-03-26 02:44:58 【问题描述】:在我的应用程序中,我想在 WKWebView 中打开 my 域(例如:communionchapelefca.org)中的链接,然后在 Safari 中打开来自 其他 域的链接。我更愿意以编程方式执行此操作。
我找到了一些关于堆栈溢出的解决方案(here、here、here 和 here),但它们似乎都是基于 Obj-C 的,我正在寻找使用 Swift 的解决方案。
ViewController.swift:
import UIKit
import WebKit
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
let myWebView:WKWebView = WKWebView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height))
myWebView.loadRequest(NSURLRequest(URL: NSURL(string: "http://www.communionchapelefca.org/app-home")!))
self.view.addSubview(myWebView)
【问题讨论】:
【参考方案1】:您可以实现WKNavigationDelegate
,添加decidePolicyForNavigationAction
方法并在那里检查navigationType 和请求的url。我在下面使用了 google.com,但您可以将其更改为您的域:
Xcode 8.3 • Swift 3.1 或更高版本
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)
else
print("Open it locally")
decisionHandler(.allow)
else
print("not a user click")
decisionHandler(.allow)
【讨论】:
这对我来说并不完全有效,例如,如果您转到developer.xamarin.com/visual-studio-mac,则使用该链接调用 devicePolicyForNavitationAction 两次,第一次使用 .LinkActivated,第二次使用 .Other,所以我最终打开了浏览器,但也浏览了 webview。 如果我使用 open() 它使用 safari 浏览器打开 url。我想在我的应用程序中使用 wkwebview 打开我的网址。我如何实现它。任何人都可以帮忙。 嗨@LeoDabus,我有一个URL,它只是改变了URL的一个参数,但这种方法无法检测到它。这是那个 URL oporun.bubbleapps.io/version-test/appernaut。单击按钮时,它只更改一个参数 Leo,您对google.com
的使用可能会产生误导,因为这正是他用作其他 网站的示例。可以修改一下吗?
我回答的最后一句很清楚IMO【参考方案2】:
这是用 obj c 编写的对 swift 的响应的示例代码。
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler
if (navigationAction.navigationType == WKNavigationTypeLinkActivated)
if (navigationAction.request.URL)
NSLog(@"%@", navigationAction.request.URL.host);
if (![navigationAction.request.URL.resourceSpecifier containsString:@"ex path"])
if ([[UIApplication sharedApplication] canOpenURL:navigationAction.request.URL])
[[UIApplication sharedApplication] openURL:navigationAction.request.URL];
decisionHandler(WKNavigationActionPolicyCancel);
else
decisionHandler(WKNavigationActionPolicyAllow);
else
decisionHandler(WKNavigationActionPolicyAllow);
【讨论】:
不推荐使用没有其他参数的 openURL。使用:[[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@ completionHandler:nil];【参考方案3】:对于 Swift 3.0
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate
let wv = WKWebView(frame: UIScreen.main.bounds)
override func viewDidLoad()
super.viewDidLoad()
guard let url = NSURL(string: "https://www.google.com") else return
wv.navigationDelegate = self
wv.load(NSURLRequest(url: url as URL) as URLRequest)
view.addSubview(wv)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
if navigationAction.navigationType == .LinkActivated
if let newURL = navigationAction.request.url,
let host = newURL.host , !host.hasPrefix("www.google.com") &&
UIApplication.shared.canOpenURL(newURL) &&
UIApplication.shared.openURL(newURL)
print(newURL)
print("Redirected to browser. No need to open it locally")
decisionHandler(.cancel)
else
print("Open it locally")
decisionHandler(.allow)
else
print("not a user click")
decisionHandler(.allow)
【讨论】:
【参考方案4】:George Vardikos 回答的 Swift 4 更新:
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
let url = navigationAction.request.url
guard url != nil else
decisionHandler(.allow)
return
if url!.description.lowercased().starts(with: "http://") ||
url!.description.lowercased().starts(with: "https://")
decisionHandler(.cancel)
UIApplication.shared.open(url!, options: [:], completionHandler: nil)
else
decisionHandler(.allow)
【讨论】:
把上面的代码放到你的 ViewController 类中,并在类声明中添加 WKUIDelegate:` class ViewController: UIViewController, WKUIDelegate ` 并在 viewDidLoad: mywebView.delegate = self 中添加【参考方案5】:我的 swift 3 解决方案:
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
let url = navigationAction.request.url
if url?.description.lowercased().range(of: "http://") != nil || url?.description.lowercased().range(of: "https://") != nil
decisionHandler(.cancel)
UIApplication.shared.openURL(url!)
else
decisionHandler(.allow)
别忘了设置代理
public override func loadView()
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
webView.navigationDelegate = self
view = webView
【讨论】:
【参考方案6】:创建一个函数来决定在哪里加载 URL:
func loadURLString(str: String)
guard let url = NSURL(string: str) else
return
if url.host == "www.communionchapelefca.org"
// Open in myWebView
myWebView.loadRequest(NSURLRequest(URL: url))
else
// Open in Safari
UIApplication.sharedApplication().openURL(url)
用法:
loadURLString("http://www.communionchapelefca.org/app-home") // Open in myWebView
loadURLString("http://www.apple.com") // Open in Safari
【讨论】:
抱歉,我花了这么长时间才回复你,但是当我点击我的 webview 中的外部链接时,你的代码不起作用,它仍然在 webview 中打开它。【参考方案7】:Swift 5 和 ios >10
不要使用UIApplication.shared.openURL(url!)
,它已被弃用。我们改用UIApplication.shared.open(url!)
。
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
guard let url = navigationAction.request.url else
decisionHandler(.allow)
return
let urlString = url.absoluteString.lowercased()
if urlString.starts(with: "http://") || urlString.starts(with: "https://")
decisionHandler(.cancel)
UIApplication.shared.open(url, options: [:])
else
decisionHandler(.allow)
【讨论】:
由于某种原因,我的委托中没有调用此方法。我的WKNavigationDelegate
中的所有其他方法都被调用,但不是这个。有谁知道这可能是什么原因造成的?以上是关于WKWebView 在 safari 中打开来自某个域的链接的主要内容,如果未能解决你的问题,请参考以下文章
在 Safari 中打开其他网站的 WKWebView 链接
从 WKWebView 调用时,无法使用 JavaScript 在移动 Safari 中打开链接