Swift WKWebView在didFailProvisionalNavigation上崩溃

时间:2017-02-10 21:31:28

标签: ios swift exception switch-statement webkit

我们遇到间歇性(在某些设备上发生,有些时候发生)崩溃,我们很难确定,并且无法按需重现。这与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
}

错误堆栈表明:

0 _BridgedStoredNSError.code.getter

1 _BridgedStoredNSError.code.getter

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

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

...

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

尝试人为地导致可能解释该问题的错误到目前为止还没有提供太多的见解。即。如果我在没有代码属性的情况下创建自己的自定义错误,那么尝试将其转换为URLError,它会优先地脱离可选的赋值。

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

1 个答案:

答案 0 :(得分:2)

在查看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
}