noa*_*mtm 3 cocoa nserror ios swift
我已经阅读了有关改进桥接和其他一些在线资源的 Swift Evolution帖子,但仍然缺少某些内容。
鉴于此自定义Error枚举:
public enum MyNetworkError: Error {
case networkOffline
case httpError(status: Int)
case unknown
case systemError(errno: Int)
}
Run Code Online (Sandbox Code Playgroud)
Objective-C 应用程序应该能够读取错误对象并以某种方式提取错误名称 ( networkOffline, httpError, unknown, systemError) 和 case 参数 ( httpError.statusand systemError.errno)。
将上述转换为的结果NSError令人惊讶,我正在尝试了解如何改进:
let nse_A = MyNetworkError.networkOffline as NSError
let nse_B = MyNetworkError.httpError(status: 503) as NSError
let nse_C = MyNetworkError.unknown as NSError
let nse_D = MyNetworkError.systemError(42) as NSError
Run Code Online (Sandbox Code Playgroud)
首先是生成的错误代码。似乎有参数的案例,无论顺序如何,都是code从零开始的:
print(nse_A.code) // 2 (expected: 0)
print(nse_B.code) // 0 (expected: 1)
print(nse_C.code) // 3 (expected: 2)
print(nse_D.code) // 1 (expected: 3)
Run Code Online (Sandbox Code Playgroud)
给定应用程序报告的错误代码,现在很难说出实际的错误情况。
其次,我期望这种智能机制(尤其是因为它是编译器生成的)也将 case 参数复制到userInfo字典中 - 但事实并非如此。
是我做错了,还是我必须完全实现CustomNSError协议才能获得有意义且一致的NSError对象?当然,这是一个选项,但我希望它会自动完成(有点像Codable它的魔力)。
此外,应用程序能否将错误案例名称作为String?
作为参考,上面的代码片段是在 Xcode 10.3 Playground 中执行的。
简短回答: 对于基于整数的枚举错误类型,错误值NSError按预期映射到代码。对于所有其他错误类型(如具有关联值的枚举),您必须实现CustomNSError协议以控制NSError代码和用户信息。
一些细节:仅对于基于整数的错误类型,代码从 Swift 桥接到NSError,例如:
public enum IntNetworkError: Int, Error {
case networkOffline = 13
case httpError
case unknown
case systemError
}
let err = IntNetworkError.httpError as NSError
print(err.code) // 14
Run Code Online (Sandbox Code Playgroud)
这是在ErrorType.swift 中实现的特殊情况 。对于所有其他错误类型,默认实现在ErrorDefaultImpls.cpp 中,它返回枚举类型和1所有其他类型的“标签” 。例子:
struct StringError: Error {}
let serr = StringError() as NSError
print(serr.code) // 1
Run Code Online (Sandbox Code Playgroud)
枚举“标签”在类型布局文档中进行了描述。对于具有关联值的枚举,这不一定遵循声明案例的顺序。这就是您观察到“意外”NSError代码的原因。
因此正确的做法是实现CustomNSError协议,编译器不会为你综合。
extension MyNetworkError: CustomNSError {
public static var errorDomain: String {
return "MyNetworkError"
}
public var errorCode: Int {
switch self {
case .networkOffline: return 1
case .httpError: return 2
case .unknown: return 3
case .systemError: return 4
}
}
public var errorUserInfo: [String : Any] {
switch self {
case .httpError(let status):
return [ "status": status]
case .systemError(let errno):
return [ "errno": errno]
default:
return [:]
}
}
}
let nse_B = MyNetworkError.httpError(status: 503) as NSError
print(nse_B.code) // 2
print(nse_B.userInfo) // ["status": 503]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1305 次 |
| 最近记录: |