【发布时间】:2016-12-07 16:03:36
【问题描述】:
我在 Swift 中有一个 enum Foo: String(因此不能导出到 Objective-C),我正在尝试在 Swift 中创建另一个枚举 FooObjc 来有点“包装”现有的枚举,以便它 1) 可用于用于 Objective-C 和 2) 可来回转换 (Foo FooObjc)。原始的Foo 枚举是我不想修改的框架的一部分。当然,如果我改用一个类,就很容易做我想做的事,像这样:
@objc public class FooObjc: NSObject {
public private(set) var foo: Foo
@objc public var string: String {
return foo.rawValue
}
@objc public init?(string: NSString) {
guard let foo = Foo(rawValue: string as String) else {
return nil
}
self.foo = foo
}
internal init(foo: Foo) {
self.foo = foo
}
}
(PS:无法从 NSString 继承,因为 Swift 编译器仍然不接受为该类创建初始化程序)
好的,但我绝对不喜欢这种方法,因为那样我的 Objective-C 代码将是字符串类型的。我真的很想改用enum,因为毕竟就是这样。这是我能得到的最差的工作版本:
@objc public enum FooObjc: Int, RawRepresentable {
case undefined = -1
case bar
case baz
// omitting many more cases
internal init?(_ foo: Foo?) {
if let foo = foo {
self = fooMapping.filter { $1 == foo }.map { $0.key }.first!
} else {
self = .undefined
}
}
// MARK: - RawRepresentable
public typealias RawValue = String
public init?(rawValue: RawValue) {
let filter = fooMapping.filter { $1?.rawValue == rawValue }
guard filter.count > 0 else {
return nil
}
self = filter.map { $0.key }.first!
}
public var rawValue: RawValue {
switch (self) {
case .undefined: return "undefined"
case .bar: return Foo.bar.rawValue
case .baz: return Foo.baz.rawValue
// omitting many more cases
}
}
}
private let fooMapping: [FooObjc: Foo?] = [
.undefined : nil,
.bar : .bar,
.baz : .baz
// omitting many more cases
]
注意:
-
fooMapping有助于避免每个初始化程序都使用一个 switch-case - 这个
undefinedcase 是必要的,因为在Swift 中你可以有可选的enum属性,而在Objective-C 中你不能,所以这个case 将直接映射到一个Foo?,其值为nil。
这里让我担心的是,我必须将原始 Foo 的相同案例写三次次......如果我只重复两次,我就完全满意了,但我不能在rawValue 属性中使用fooMapping,因为那样我会在这两者之间得到一个循环。
注意:我不确定这是否与问题相关,但在原始enum 中,某些情况具有特殊的字符串属性,例如我们只有case bar,但我们也有case baz = "something"。
那么,问题是:有没有人提出改进这种方法的建议,甚至提出一些全新的方法来避免如此多的代码重复?
非常感谢!
【问题讨论】:
标签: objective-c swift enums