Skip to content

Instantly share code, notes, and snippets.

@acalism
Last active January 30, 2018 13:13
Show Gist options
  • Save acalism/b5e3155719d778ca2d229932dbccd96b to your computer and use it in GitHub Desktop.
Save acalism/b5e3155719d778ca2d229932dbccd96b to your computer and use it in GitHub Desktop.
extension WKWebView {
/// sync version
///
/// - Parameters:
/// - js: 要执行的javascript代码
/// - timeout: 限时返回(单位秒),0表示不限时
/// - Returns: 执行结果
func evaluatingJavaScript(_ js: String, timeout: TimeInterval = 0) -> Any? {
var res: Any? = nil
var finish = false
var count = 0, maxCount = Int(timeout * 10) // 0.1秒为间隔
evaluateJavaScript(js) { (result, error) in
res = result
finish = true
}
while !finish {
RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))
if maxCount > 0 && count >= maxCount {
finish = true
}
count += 1
}
return res
}
}
enum URLType {
case about
case http // 普通的 http(s)
case appStore
case map
case custom // 例如 weiyun://, txent:
}
extension URLComponents {
var type: URLType {
let s = scheme?.lowercased()
if s == "http" || s == "https" {
let h = host?.lowercased()
if h == "itunes.apple.com" { // 居然不是 Universal Link,亮瞎
return .appStore
}
if h == "maps.apple.com" && query != nil {
return .map
}
return .http
}
if s == "about" {
return .about
}
return .custom
}
}
// MARK: - WKNavigationDelegate
func webView(_ wv: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url, let uc = URLComponents(url: url, resolvingAgainstBaseURL: true), let _ = uc.scheme else {
print("这个request不正常\(navigationAction.request)")
decisionHandler(.cancel)
return
}
handleURL(url, decisionHandler: decisionHandler)
}
func handleURL(_ url: URL, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// url 可能是 about:blank,即 navigationAction.targetFrame == nil,亦即 target="_blank"
// 典型例子:“软件许可及服务协议”跳转到“微信公众平台服务协议”后再跳转时
guard let uc = URLComponents.init(url: url, resolvingAgainstBaseURL: true) else {
decisionHandler(.cancel)
return
}
let t = uc.type
switch t {
case .http:
handleHttpURL(url, decisionHandler: decisionHandler)
case .about:
decisionHandler(.allow)
case .appStore, .map:
decisionHandler(.cancel)
// 保持跟微信的体验一致
let appName = t == .appStore ? "App Store" : "地图"
let ac = UIAlertController(title: nil, message: "将会离开\"\(Global.displayName)\"\n并跳转到\(appName)", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "取消", style: .cancel))
ac.addAction(UIAlertAction(title: "确定", style: .default, handler: { (aa) in
UIApplication.shared.openURL(url)
log.i("open application with url: \(url)")
}))
present(ac, animated: true, completion: nil)
case .custom:
decisionHandler(.cancel)
handleCustomURL(url)
}
}
/// Can be override
/// 需识别 universal link
func handleHttpURL(_ url: URL, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
decisionHandler(.allow)
}
/// Can be override
func handleCustomURL(_ url: URL) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(url)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment