将Error转换为NSError时,Swift 3自定义URLProtocol崩溃

时间:2017-05-09 01:22:39

标签: swift macos swift3 crash nserror

我有一个相当大的Swift 3代码用于Mac OS 10.11及更高版本(使用Xcode 8.2.1)。有许多进程,其中包括GUI应用程序和后台服务。这两个都使用自定义URLProtocol,它在框架中实现(由应用程序和服务导入)。协议有时可能会生成符合enum的{​​{1}}实例,它会捕获并适当处理(通常通过使用URLProtocolClient将它们抛到尝试发出请求的URLSession)。

  • 当没有错误时,应用和服务都可以正常工作。
  • 出现错误时,应用程序正常运行(正如预期的那样)。
  • 如果出现错误,服务崩溃

漫游调试器表明,当Error被运行时自动转换为Error时,就会发生此崩溃。我在我的代码中明确添加了这个强制转换,当然,我现在也遇到了同样的崩溃。

我看到了Swift 3.1: Crash when custom error is converted to NSError to access its domain property,但这里不适用:

  • 那里的解决方案 - 将NSError扩展为Error(以及CustomNSError以获得良好衡量标准)并实施相关属性 - 并没有帮助。
  • 在获得LocalizedError后发生崩溃;据我所知,这对我来说不是问题。
  • 可能相关:那是在iOS上,而不是Mac。

我已经尝试过这个问题的唯一列出的解决方案,我有点不知所措。我已经调试了好几个小时没有到达任何地方,除了它似乎发生在domain的深处某处。

代码:

dyld

我解决这个问题的一个想法就是使用enum CrowbarProtocolError: Error { case FailedToCreateSocket; case PathTooLong; case NonSocketFile; case SocketNotFound; ... case UnrecognizedError(errno: Int32); } extension CrowbarProtocolError: LocalizedError { public var errorDescription: String? { return "Some localized description" } } extension CrowbarProtocolError: CustomNSError { public static var errorDomain: String { return "Some Domain Name" } public var errorCode: Int { return 204 //Should be your custom error code. } public var errorUserInfo: [String: Any] { return ["WTF": "Swift?"]; } } ... open class CrowbarUrlProtocol: URLProtocol { ... override open func startLoading() { do { let sockHandle = try CrowbarUrlProtocol.openSocket(); let req = try buildRequestData(); sockHandle.write(req); NotificationCenter.default.addObserver( self, selector: #selector(self.readCompleted), name: .NSFileHandleReadToEndOfFileCompletion, object: nil); sockHandle.readToEndOfFileInBackgroundAndNotify(); } catch let err { Log.warn("CrowbarUrlProtocol request failed with error \(err)"); // -- In the background service, THIS LINE CRASHES! -- let err2 = err as NSError; Log.warn("As NSError: \(err2)"); // -- Without the explicit cast, it crashes on this line -- self.client?.urlProtocol(self, didFailWithError: err); } } ... } 来做所有事情(或尽可能多),理由是如果从来没有必要将NSError转换为{ {1}},然后不会发生导致此崩溃的任何事情。不知道它是否会起作用,但似乎值得一试......

1 个答案:

答案 0 :(得分:0)

好的,据我所知,这只是Swift运行时的一个错误,但我找到了解决办法:只使用NSError来处理涉及Obj-C代码的所有内容而不是Swift { {1}} s(避免隐式转换)。由于我已经在实施Error,因此很容易在我的CustomNSError枚举上创建toNSError()函数,并将其用于Error行。

self.client?.urlProtocol(self, didFailWithError: err)