我有一个相当大的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
后发生崩溃;据我所知,这对我来说不是问题。我已经尝试过这个问题的唯一列出的解决方案,我有点不知所措。我已经调试了好几个小时没有到达任何地方,除了它似乎发生在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}},然后不会发生导致此崩溃的任何事情。不知道它是否会起作用,但似乎值得一试......
答案 0 :(得分:0)
好的,据我所知,这只是Swift运行时的一个错误,但我找到了解决办法:只使用NSError
来处理涉及Obj-C代码的所有内容而不是Swift { {1}} s(避免隐式转换)。由于我已经在实施Error
,因此很容易在我的CustomNSError
枚举上创建toNSError()
函数,并将其用于Error
行。
self.client?.urlProtocol(self, didFailWithError: err)