gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 12:28:40 32 4
gpt4 key购买 nike

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

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

在调试器中徘徊表明,当运行时将 Error 自动转换为 NSError 时,就会发生此崩溃。我在代码中显式添加了此转换,果然,我在该行上遇到了相同的崩溃。

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

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

在尝试了该问题唯一列出的解决方案后,我有些不知所措。我已经调试了几个小时,除了它似乎发生在 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 做所有事情(或者尽可能多地),因为如果永远不需要转换 ErrorNSError,那么导致此崩溃的任何原因都不会发生。不知道它是否有效,但似乎值得一试......

最佳答案

好吧,据我所知,这只是 Swift 运行时中的一个错误,但我找到了一个解决方法:只需对涉及 Obj-C 代码而不是 Swift 的所有内容使用 NSError >错误(以避免隐式转换)。由于我已经实现了 CustomNSError,因此很容易在我的 Error 枚举上创建一个 toNSError() 函数,并将其用于 self.client?.urlProtocol(self, didFailWithError: err) 行。

enum CrowbarProtocolError: Error, CustomNSError {
case FailedToCreateSocket;
case PathTooLong;
...
public func asNSError() -> NSError {
return NSError(domain: CrowbarProtocolError.errorDomain,
code: self.errorCode,
userInfo: self.errorUserInfo);
}
}
...
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 as CrowbarProtocolError {
Log.warn("CrowbarUrlProtocol request failed with error \(err)");
self.client?.urlProtocol(self, didFailWithError: err.asNSError());
}
catch let err {
Log.warn("CrowbarUrlProtocol caught non-CrowbarProtocol Error \(err)");
// This would probably crash the service, but shouldn't ever happen
self.client?.urlProtocol(self, didFailWithError: err);
}
}
...
}

关于将 Error 转换为 NSError 时,Swift 3 自定义 URLProtocol 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43859552/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com