免责声明/TL;DR!这个答案与技术问题有关,即我们是否可以在我们自己的不同 Swift 类型之间实现隐式桥接机制。答案是:在某些情况下,是的,但仅在有限的意义上和通过“黑客”的方式:不要使用这是生产代码!
Swift 内部协议滥用:我们可能会为 Obj-C 对象实现隐式机制(例如NSNumber、NSString ...)
正如 MartinR 在他的评论中所写,(本机)Swift 不存在自定义转换方法。
对于技术讨论,但是,我们可以(ab)使用内部协议_ObjectiveCBridgeable 来允许从您的枚举到 Obj-C 对象的隐式桥接,在这种情况下,例如NSString。内部协议_ObjectiveCBridgeable主题更详细的问答,见
在继续之前,我将在上面的帖子中引用我的回答中的免责声明:
...注意_ObjectiveCBridgeable 是一个内部/隐藏协议
(_UnderScorePreFixedProtocol),因此基于它的解决方案可能会中断
在即将发布的 Swift 版本中没有警告。
示例 #1:实现枚举到 NSString 的隐式桥接
首先让我们为您的枚举添加一个可失败的初始化程序,允许String 实例进行(尝试)初始化:
import Foundation
enum MyEnum: Int {
case Case1 = 0
case Case2
init?(string: String) {
switch string {
case "Case 1": self = .Case1
case "Case 2": self = .Case2
default: return nil
}
}
}
接下来,让MyEnum符合_ObjectiveCBridgeable,如thread linked to above中更详细的描述
extension MyEnum: _ObjectiveCBridgeable {
typealias _ObjectiveCType = NSString
static func _isBridgedToObjectiveC() -> Bool {
return true
}
static func _getObjectiveCType() -> Any.Type {
return _ObjectiveCType.self
}
func _bridgeToObjectiveC() -> _ObjectiveCType {
return NSString(string: "Case \(self.rawValue+1)")
}
static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyEnum?) {
result = MyEnum(string: source as String)
}
static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyEnum?) -> Bool {
self._forceBridgeFromObjectiveC(source, result: &result)
return true
}
}
有了上面的一致性,我们现在可以使用从 MyEnum 实例到 NSString 的隐式桥接
/* example usage */
var myCase: MyEnum = .Case1
var enumNSstr: NSString = myCase // MyEnum -> NSString, implicit
print(enumNSstr) // Case 1
enumNSstr = "Case 2"
// NSString -> MyEnum, by type conversion (castable)
myCase = (enumNSstr as MyEnum) ?? .Case1
print(myCase) // Case 2
示例 #2:实现枚举到自定义 Swift 本机类型的隐式桥接
我们甚至可能进一步滥用_ObjectiveCBridgeable 协议,使用它的(深后端)机制来实现两个原生 Swift 类型之间的隐式桥接,限制是桥接的类型 to 必须是引用类型(特别是:该类型的实例必须可以由AnyObject 表示,因此存在引用类型限制)。
让MyEnum 与上面的定义相同,但另外,定义一个引用(类)类型Foo,并将MyEnum 与_ObjectiveCBridgeable 与桥接to type 一致,@987654345 @被设置为Foo。
class Foo {
var bar: String
init(bar: String) { self.bar = bar }
}
extension MyEnum: _ObjectiveCBridgeable {
typealias _ObjectiveCType = Foo
static func _isBridgedToObjectiveC() -> Bool {
return true
}
static func _getObjectiveCType() -> Any.Type {
return _ObjectiveCType.self
}
func _bridgeToObjectiveC() -> _ObjectiveCType {
return Foo(bar: "Case \(self.rawValue+1)")
}
static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyEnum?) {
result = MyEnum(string: source.bar)
}
static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyEnum?) -> Bool {
self._forceBridgeFromObjectiveC(source, result: &result)
return true
}
}
我们现在可以使用从 MyEnum 实例到 Foo 的隐式桥接
/* example usage */
var myCase: MyEnum = .Case1
var myFoo: Foo = myCase // MyEnum -> Foo, implicit
print(myFoo.bar) // Case 1
myFoo.bar = "Case 2"
// Foo -> MyEnum, by type conversion (castable)
myCase = (myFoo as? MyEnum) ?? .Case1
print(myCase) // Case 2
最后请注意,对于任何给定类型(例如,MyEnum),您自然只能实现到单个其他(引用)类型的隐式桥接;因为您只能符合 _ObjectiveCType 一次(对于 typealias _ObjectiveCType 的唯一类型),否则会产生冗余协议一致性的编译时错误。
以上内容针对 Swift 2.2 进行了测试。