我有一个Objective-C文件,其枚举定义如下:
typedef NS_ENUM(NSInteger, State) {
State_ACTIVE = 0,
State_PENDING = 1,
State_CANCELED = 2
};
在我的swift代码中,如果我执行let state = State(rawValue: 100)
,通常会返回nil
,因为它是一个可用的初始化程序。但是,当枚举声明为(使用NS_ENUM
)时,初始化成功,并且没有迹象表明这是一个无效的枚举值。这是Xcode中的错误,还是按预期工作?
答案 0 :(得分:1)
这是预期的行为。对于桥接到Swift的任何NS_ENUM
,构造函数永远不会返回nil
。
尝试使用iOS SDK中的其他枚举来与Swift桥接,并带有意外值。它们都会返回非零值,即使是枚举未定义的rawValue
:
UITableViewCellStyle(rawValue: 7) // "Optional(__C.UITableViewCellStyle)"
UITableViewCellAccessoryType(rawValue: 9999) // "Optional(__C.UITableViewCellAccessoryType)"
或,unsafeBitCast
:
unsafeBitCast(42, UITableViewCellEditingStyle.self) // "Optional(__C.UITableViewCellStyle)"
Martin R指出,这是记录在案的 Xcode 6.3 release notes:
导入带有未记录值的NS_ENUM类型,例如
UIViewAnimationCurve
,现在可以从原始整数转换 使用init(rawValue:)
初始化程序而不重置的值nil
。使用unsafeBitCast
作为此问题的解决方法的代码可以 写入使用原始值初始化程序。例如:let animationCurve = unsafeBitCast(userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue, UIViewAnimationCurve.self)
现在可以改为:
let animationCurve = UIViewAnimationCurve(rawValue: userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue)!
答案 1 :(得分:0)
可以在此枚举的扩展中定义一个额外的初始化程序,并实现适合您需求的行为。
extension State
{
static var allRawCases: [Int]
{
var array = [Int]()
switch State.ACTIVE
{
case .ACTIVE:
array.append(State.ACTIVE.rawValue)
fallthrough
case .CANCELED:
array.append(State.CANCELED.rawValue)
fallthrough
case .PENDING:
array.append(State.PENDING.rawValue)
}
return array
}
}
extension State
{
init?(raw: Int)
{
guard State.allRawCases.contains(raw) else
{
return nil
}
self = State(rawValue: raw)!
}
}
优点:
在下一段代码中,最好在变量中使用nil而不是 “无效值。此值导致Swift 3 + Xcode 10崩溃 项目。
// intValue differs from raw enumeration values e.g 100
guard let state = State(rawValue: intValue) else
{
return
}
switch state
{
case .ACTIVE:
// do active staff
case .CANCELED:
// do canceled staff
case .PENDING:
// do pending staff
}
缺点: