我使用enum
定义所有自定义错误,如:
public enum MyErrorEnum: String, LocalizedError {
case FileNotFound = "Failed to find file."
public var errorDescription: String? { rawValue }
}
但有些错误需要额外的context
,比如向消息添加文件路径。
不幸的是,由于Swift枚举不支持实例变量,我尝试了一些变通方法,比如:
private var KEY_CONTEXT: UInt8 = 0;
public enum MyErrorEnum: String, LocalizedError {
case FileNotFound = "Failed to find file."
public var errorDescription: String? { rawValue }
public var context: String {
return objc_getAssociatedObject(self as NSObject, &KEY_CONTEXT)
as? String ?? "";
}
@discardableResult
public mutating func withContext(_ value: String) -> Self {
objc_setAssociatedObject(
self as NSObject, &KEY_CONTEXT, value as NSString,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return self;
}
}
注意上面的内容在Xcode 12中没有引发任何编译和/或运行时错误,只是不起作用。
后来,我收到通知,Xcode 13会引发以下编译错误:"CCD_ 3";
我也已经尝试过简单地将String
更改为实现ExpressibleByStringLiteral
的自定义StringWithContext
类,但即使这样也不起作用(可能是因为枚举的rawValue
在某种程度上受到了更改保护(。
有没有任何方法可以将额外的变量添加到所述枚举中
否,目前无法在Swift
中直接向enum
添加实例变量。
(在Java
中,这是微不足道的,因为enum
是另一个class
(。
然而,如果您坚持使用Swift的enum
,请使用具有默认值的关联枚举作为消息。
示例
只需将LocalizedErrorEnum
从下面复制并添加到您的项目中一次,然后根据需要使用关联枚举重复使用多次。
public protocol LocalizedErrorEnum: LocalizedError {
var errorDescription: String? { get }
}
extension LocalizedErrorEnum {
public var errorDescription: String? {
if let current = Mirror(reflecting: self).children.first {
let mirror = Mirror(reflecting: current.value);
// Initial error description.
let message = mirror.children.first?.value as? String
?? current.label ?? "Unknown-case";
var context = "";
// Iterate additional context.
var i = 0;
for associated in mirror.children {
if i >= 1 {
if let text = associated.value as? String {
context += "n ";
if let label: String = associated.label {
context += "(label): "
}
context += text;
}
}
i += 1;
}
return context.isEmpty ? message : (
message + " {" + context + "n}"
);
}
return "(self)";
}
}
用法:
public enum MyErrorEnum: LocalizedErrorEnum {
case FileNotFound(String = "Failed to find file.", file: String)
}
// ...
do {
let path = "/path/to/file.txt";
throw MyErrorEnum.FileNotFound(
file: path
);
} catch {
print(error.localizedDescription);
}
输出:
Failed to find file. {
file: /path/to/file.txt
}
另请参阅:在Swift中抛出自定义错误的最简单方法?