我想将两个原始值关联到枚举实例(想象一个表示错误类型的枚举,我希望Error.Teapot
具有值类型为418的Int类型属性code
,以及设置为I'm a teapot
的String属性。)
请注意raw values和associated values之间的区别 - 我希望所有Teapot
实例的code
为418,我不希望每个Teapot
实例具有唯一的关联值。
有没有比将qazxswpo在switch
上查找适当值的枚举添加计算属性更好的方法?
不,枚举不能有多个原始值 - 它必须是单个值,实现self
协议,并且可以像Equatable
中描述的那样进行字面转换。
我认为在您的情况下最好的方法是使用错误代码作为原始值,并使用预先填充的静态字典支持的属性,错误代码为键,文本为值。
不,您不能拥有与枚举关联的多个原始值。
在您的情况下,您可以使原始值等于代码,并具有与描述相关联的值。但我认为计算属性方法是最好的选择。
我创造了一种模拟这种方式(与Marcos Crispino在他的回答中提出的建议没什么不同)。远非一个完美的解决方案,但允许我们为我们想要获得的每个不同的属性避免那些讨厌的开关案例。
诀窍是使用结构作为“属性/数据”持有者并在枚举本身中将其用作RawValue。
它有一些重复,但到目前为止它对我很有帮助。每次你想添加一个新的枚举案例时,编译器会提醒你在rawValue getter中填写额外的case,这应该提醒你更新documentation,它会提醒你在struct上创建新的static属性。
init?
要点代码:
Gist
如果您想为YourError提供许多静态属性,则可以导入属性列表;您可以将根对象设置为字典,并将枚举原始值作为每个对象的键,从而可以轻松地检索对象的静态结构化数据。
这有一个导入和使用plist的例子:enum VehicleType : RawRepresentable {
struct Vehicle : Equatable {
let name: String
let wheels: Int
static func ==(l: Vehicle, r: Vehicle) -> Bool {
return l.name == r.name && l.wheels == r.wheels
}
static var bike: Vehicle {
return Vehicle(name: "Bicycle", wheels: 2)
}
static var car: Vehicle {
return Vehicle(name: "Automobile", wheels: 4)
}
static var bus: Vehicle {
return Vehicle(name: "Autobus", wheels: 8)
}
}
typealias RawValue = Vehicle
case car
case bus
case bike
var rawValue: RawValue {
switch self {
case .car:
return Vehicle.car
case .bike:
return Vehicle.bike
case .bus:
return Vehicle.bus
}
}
init?(rawValue: RawValue) {
switch rawValue {
case Vehicle.bike:
self = .bike
case Vehicle.car:
self = .car
case Vehicle.bus:
self = .bus
default: return nil
}
}
}
VehicleType.bike.rawValue.name
VehicleType.bike.rawValue.wheels
VehicleType.car.rawValue.wheels
VehicleType(rawValue: .bike)?.rawValue.name => "Bicycle"
VehicleType(rawValue: .bike)?.rawValue.wheels => 2
VehicleType(rawValue: .car)?.rawValue.name => "Automobile"
VehicleType(rawValue: .car)?.rawValue.wheels => 4
VehicleType(rawValue: .bus)?.rawValue.name => "Autobus"
VehicleType(rawValue: .bus)?.rawValue.wheels => 8
对于简单的错误描述而言,这可能是过度的,您可以使用硬编码的静态函数和您的枚举值的switch语句,返回您需要的错误字符串。只需将静态函数放在与枚举相同的.swift文件中即可。
例如,
http://www.spritekitlessons.com/parsing-a-property-list-using-swift/
这具有更好的容纳本地化的好处(与.plist解决方案相比)。但是,.plist可能只包含用于检索正确本地化的密钥,而不是用于此目的的错误字符串。
你有几个选择。但它们都不涉及原始价值。原始值不是该任务的正确工具。
我个人强烈建议每个enum案例中有多个关联值。相关的值应该是显而易见的(因为它们没有参数/名称),并且水中有多个重度混乱。
也就是说,这是语言让你做的事情。这允许您以不同的方式定义每个案例,如果这是您需要的。例:
static func codeForError(error : YourErrorType) -> Int {
switch(error) {
case .Teapot:
return "I'm a Teapot"
case .Teacup:
return "I'm a Teacup"
...
default:
return "Unknown Teaware Error"
}
}
元组是Swift的一大特色,因为它们为您提供了创建特殊类型的能力。这意味着您可以在线定义它。甜!
如果你的每个错误类型都有代码和描述,那么你可以有一个计算的enum ErrorType {
case teapot(String, Int)
case skillet(UInt, [CGFloat])
}
属性(希望有一个更好的名字?)。见下文:
info
调用它会更容易,因为你可以使用美味的点语法:
enum ErrorType {
case teapot
case skillet
var info: (code: Int, description: String) {
switch self {
case .teapot:
return (418, "Hear me shout!")
case .skillet:
return (326, "I'm big and heavy.")
}
}
}
这并没有特别回答你的问题,它要求找到一个比let errorCode = myErrorType.info.code
ing更好的方法来通过switch
来查找合适的值,但这个答案对于将来需要一种简单方法来获取字符串的人来说仍然有用。枚举,定义为整数类型。
self
这样,我们可以通过两种方式获取errorMessage:
enum Error: UInt {
case Teapot = 418
case Kettle = 419
static func errorMessage(code: UInt) -> String {
guard let error = Error(rawValue: code) else {
return "Unknown Error Code"
}
switch error {
case .Teapot:
return "I'm a teapot!"
case .Kettle:
return "I'm a kettle!"
}
}
}
)选项1:
rawValue
选项2:
let option1 = Error.errorMessage(code: 418)
print(option1) //prints "I'm a teapot!"
在Swift的现代版本中,即使没有使用let option2 = Error.errorMessage(code: Error.Teapot.rawValue)
print(option2) //prints "I'm a teapot!"
rawValue声明枚举,也可以获得枚举案例标签的字符串值。
: String
因此,不再需要定义和维护一个便利功能,该功能可以打开每个案例以返回字符串文字。此外,即使没有指定原始值类型,这也适用于任何枚举。
至少,这允许您通过同时使用真正的How to get the name of enumeration value in Swift? rawValue以及用作案例标签的字符串来获得“多个原始值”。
首先,假设您要存储代码和消息,可以使用: Int
的结构
RawValue
下一步是将枚举定义为struct ErrorInfo {
let code: Int
let message: String
}
,并使用RawRepresentable
作为原始值:
ErrorInfo
剩下的是在enum MyError: RawRepresentable {
typealias RawValue = ErrorInfo
case teapot
和MyError
的实例之间进行映射:
ErrorInfo
有了上面的内容,让我们构建枚举的完整定义:
static private let mappings: [(ErrorInfo, MyError)] = [
(ErrorInfo(code: 418, message: "I'm a teapot"), .teapot)
]
一些说明:
可能的解决方法是将自定义函数与枚举关联起来
enum MyError: RawRepresentable {
static private let mappings: [(ErrorInfo, MyError)] = [
(ErrorInfo(code: 418, message: "I'm a teapot"), .teapot)
]
case teapot
init?(rawValue: ErrorInfo) {
guard let match = MyError.mappings.first(where: { $0.0.code == rawValue.code && $0.0.message == rawValue.message}) else {
return nil
}
self = match.1
}
var rawValue: ErrorInfo {
return MyError.mappings.first(where: { $0.1 == self })!.0
}
}
可以用作
enum ToolbarType : String{
case Case = "Case", View="View", Information="Information"
static let allValues = [Case, View, Information]
func ordinal() -> Int{
return ToolbarType.allValues.index(of: self)!
}
}
产量
for item in ToolbarType.allValues {
print("\(item.rawValue): \(item.ordinal())")
}
可能您可以使用其他功能将枚举类型与不同的值相关联