Swift WKWebView 在 didFailProvisionalNavigation 上崩溃

Glo*_*del 6 webkit exception switch-statement ios swift

我们遇到了间歇性崩溃(有时会在某些设备上发生),我们很难确定该崩溃,并且无法按需重现。这与 Swift 3 和 WKWebView 组件有关,特别是当尝试通过 switch 语句获取错误代码时,其回调协议崩溃。见下文:

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {

  if let err = error as? URLError {

    switch(err.code) {  //  Exception occurs on this line
    case .cancelled:
      Hint(hide: true)

    case .cannotFindHost:
      Hint(hide: false, hint:.CannotFindHost)

    case .notConnectedToInternet:
      Hint(hide: false, hint: .NoInternet)

    case .resourceUnavailable:
      Hint(hide: false)

    case .timedOut:
      Hint(hide: false)

    default:
      Hint(hide: false)
      print("error code: " + String(describing: err.code) + "  does not fall under known failures")
    }
  }
}

func Hint(hide: Bool, hint:SomeCustomEnum = SomeCustomEnum.Default) {
     //Dosomething with ui to let user know something bad happened
}
Run Code Online (Sandbox Code Playgroud)

错误堆栈指示:

0 _BridgedStoredNSError.code.getter

1 _BridgedStoredNSError.code.getter

2 专门的WebKitController.webView(WKWebView, didFailProvisionalNavigation : WKNavigation!, withError : Error) -> ()

3 @obj WebKitController.webView(WKWebView, didFailProvisionalNavigation : WKNavigation!, withError : 错误) -> ()

...

查看代码,似乎应该有效地消除问题,因为在调用 switch 语句时,变量 err 应该成功地选择性地解包为有效的 URLError 对象。此时的 switch 语句应该保证 err.code 中的值,因为 .code 对于 URLError 不是可选的。

迄今为止,人为造成可能解释该问题的错误的尝试尚未提供太多见解。IE。如果我在没有 code 属性的情况下创建自己的自定义错误,然后尝试将其转换为 URLError,它会优雅地脱离可选分配。

任何有关旋转甚至进一步故障排除的帮助或建议都值得赞赏,同时将继续尝试在一致的基础上重现。

Glo*_*del 5

在查看 Swift Bug ( https://bugs.swift.org ) 提交网站时,我找到了问题的描述,即。错误转换为 URLError 可能会导致属性 .code 丢失:

https://bugs.swift.org/browse/SR-3879?jql=text%20~%20%22URLError%22

这有一个指向以下参考文献的链接,这似乎是解决方案(仍在进行中)

https://bugs.swift.org/browse/SR-3881

实际上 URLError 缺少两个 .code 定义:

NSURLErrorAppTransportSecurityRequiresSecureConnection NSURLErrorDataLengthExceedsMaximum

因此,如果您在引用 URLError 的 .code 属性时遇到崩溃,您可以通过转换为 NSError 并检查 NSError .code 属性来检查崩溃。

我们正在使用临时解决方法来缓解该问题,直到错误得到解决(下面仅解决 NSURLErrorAppTransportSecurityRequiresSecureConnection (int -1022) 类型故障):

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {

  let nserr = error as NSError
  if nserr.code == -1022 {
    Hint(hide: false, hint: .NSURLErrorAppTransportSecurityRequiresSecureConnection)

  } else if let err = error as? URLError {

    switch(err.code) {  //  Exception no longer occurs
    case .cancelled:
      Hint(hide: true)

    case .cannotFindHost:
      Hint(hide: false, hint:.CannotFindHost)

    case .notConnectedToInternet:
      Hint(hide: false, hint: .NoInternet)

    case .resourceUnavailable:
      Hint(hide: false)

    case .timedOut:
      Hint(hide: false)

    default:
      Hint(hide: false)
      print("error code: " + String(describing: err.code) + "  does not fall under known failures")
    }
  }
}

func Hint(hide: Bool, hint:SomeCustomEnum = SomeCustomEnum.Default) {
     //Dosomething with ui to let user know something bad happened
}
Run Code Online (Sandbox Code Playgroud)