是否使用实例变量枚举?(Swift)



我使用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中抛出自定义错误的最简单方法?

最新更新