I have an enum that is codable:
public enum MyEnum: String, Codable, Hashable, Sendable {
case one = "ONE"
case two = "TWO"
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(RawValue.self)
self = MyEnum(rawValue: rawValue) ?? .one
}
}
However, I now need to make this compatible with objective-c. I know that I can't have a String
raw value, and it must be Int
. I still need it to be compatible like before, as it's being created from JSON which is a string and not an Int. How do I do this?
CodePudding user response:
Rather than modifying your pure Swift type to expose it to Obj-C and hence restricting the language features that you can use, I'd suggest creating a separate bridge type that you expose to Obj-C.
This approach makes it much easier to model your data using the full capabilities of Swift and also make it easier to remove your Obj-C compatible types once your codebase is fully migrated to Swift (or at least all parts of it that require access to this type).
@objc public enum MyEnumBridge: Int {
case one
case two
}
Now add an extension to your Obj-C compatible type to initialise it from your pure Swift type:
extension MyEnumBridge {
init(wrapped: MyEnum) {
switch wrapped {
case .one:
self = .one
case .two:
self = .two
}
}
}
You can call the init from a Swift extension of your Obj-C type, but still store/use the enum in Obj-C.
And for converting the Obj-C type back to Swift:
extension MyEnumBridge {
var wrapped: MyEnum {
switch self {
case .one:
self = .one
case .two:
self = .two
}
}
}
CodePudding user response:
Okay I think I came up with a solution (correct me if I'm wrong!)
public enum MyEnum: Int, Codable, Hashable, Sendable {
case one
case two
enum InternalMyEnum: String, Codable {
case one = "ONE"
case two = "TWO"
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .one:
try container.encode(InternalMyEnum.one.rawValue)
case .two:
try container.encode(InternalMyEnum.two.rawValue)
}
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(String.self)
let internalMyEnum = InternalMyEnum(rawValue: rawValue) ?? .one
switch internalVariantType {
case .one:
self = .one
case .one:
self = .one
}
}
}