I define all custom Errors using enum(s), like:
public enum MyErrorEnum: String, LocalizedError {
case FileNotFound = "Failed to find file."
public var errorDescription: String? { rawValue }
}
But some errors require additional context, like adding file-path to the message.
Unfortunately, because Swift enums don't support instance variables, I tried workarounds, like:
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;
}
}
Note that above does not raise any compile and/or runtime error in Xcode 12, but just did not work.
And later, I was notified that Xcode 13 raises compile error below: "
Cannot convert value of type 'MyErrorEnum' to type 'NSObject' in coercion"
I also already tried simply changing String to a custom StringWithContext class which implements ExpressibleByStringLiteral, but NOT even that did work (probably because enum's rawValue is somehow change protected).
No, currently there is no way to add instance variable to
enumdirectly inSwift.(in
Javathat's trivial, as thereenumis yet anotherclass).However, if you insist on using Swift's
enum, use associative-enum with default value as message.Example
Simply, copy and add
LocalizedErrorEnumfrom below into your project once, and reuse as many times as required with associative-enums.Usage:
Output:
See also: Simplest way to throw custom error in Swift?