enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
例如,我怎么做这样的事情:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
结果示例:
♠
♥
♦
♣
enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
例如,我怎么做这样的事情:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
结果示例:
♠
♥
♦
♣
当前回答
我添加了函数count(),并迭代值:
public enum MetricType: Int {
case mvps = 0
case allNBA = 1
case championshipRings = 2
case finalAppearances = 3
case gamesPlayed = 4
case ppg = 5
static func count() -> Int {
return (ppg.rawValue) + 1
}
static var allValues: [MetricType] {
var array: [MetricType] = Array()
var item : MetricType = MetricType.mvps
while item.rawValue < MetricType.count() {
array.append(item)
item = MetricType(rawValue: (item.rawValue + 1))!
}
return array
}
}
其他回答
我发现了一种有点俗气但更安全的方法,它不需要键入两次值或引用枚举值的内存,因此不太可能损坏。
基本上,与其使用枚举,不如创建一个具有单个实例的结构体,并将所有enum-values设置为常量。然后可以使用Mirror查询变量
public struct Suit{
// the values
let spades = "♠"
let hearts = "♥"
let diamonds = "♦"
let clubs = "♣"
// make a single instance of the Suit struct, Suit.instance
struct SStruct{static var instance: Suit = Suit()}
static var instance : Suit{
get{return SStruct.instance}
set{SStruct.instance = newValue}
}
// an array with all of the raw values
static var allValues: [String]{
var values = [String]()
let mirror = Mirror(reflecting: Suit.instance)
for (_, v) in mirror.children{
guard let suit = v as? String else{continue}
values.append(suit)
}
return values
}
}
如果使用此方法,则需要使用Suit.instance.clubs或Suit.instance.spades来获取单个值
但所有这些都太无聊了……让我们做一些事情,使它更像一个真正的enum!
public struct SuitType{
// store multiple things for each suit
let spades = Suit("♠", order: 4)
let hearts = Suit("♥", order: 3)
let diamonds = Suit("♦", order: 2)
let clubs = Suit("♣", order: 1)
struct SStruct{static var instance: SuitType = SuitType()}
static var instance : SuitType{
get{return SStruct.instance}
set{SStruct.instance = newValue}
}
// a dictionary mapping the raw values to the values
static var allValuesDictionary: [String : Suit]{
var values = [String : Suit]()
let mirror = Mirror(reflecting: SuitType.instance)
for (_, v) in mirror.children{
guard let suit = v as? Suit else{continue}
values[suit.rawValue] = suit
}
return values
}
}
public struct Suit: RawRepresentable, Hashable{
public var rawValue: String
public typealias RawValue = String
public var hashValue: Int{
// find some integer that can be used to uniquely identify
// each value. In this case, we could have used the order
// variable because it is a unique value, yet to make this
// apply to more cases, the hash table address of rawValue
// will be returned, which should work in almost all cases
//
// you could also add a hashValue parameter to init() and
// give each suit a different hash value
return rawValue.hash
}
public var order: Int
public init(_ value: String, order: Int){
self.rawValue = value
self.order = order
}
// an array of all of the Suit values
static var allValues: [Suit]{
var values = [Suit]()
let mirror = Mirror(reflecting: SuitType.instance)
for (_, v) in mirror.children{
guard let suit = v as? Suit else{continue}
values.append(suit)
}
return values
}
// allows for using Suit(rawValue: "♦"), like a normal enum
public init?(rawValue: String){
// get the Suit from allValuesDictionary in SuitType, or return nil if that raw value doesn't exist
guard let suit = SuitType.allValuesDictionary[rawValue] else{return nil}
// initialize a new Suit with the same properties as that with the same raw value
self.init(suit.rawValue, order: suit.order)
}
}
你现在可以做
let allSuits: [Suit] = Suit.allValues
or
for suit in Suit.allValues{
print("The suit \(suit.rawValue) has the order \(suit.order)")
}
然而,要获得一个单一,你仍然需要使用SuitType.instance.spades或SuitType.instance.hearts。为了更加直观,您可以向Suit添加一些允许您使用Suit.type的代码。*而不是SuitType.instance.*
public struct Suit: RawRepresentable, Hashable{
// ...your code...
static var type = SuitType.instance
// ...more of your code...
}
您现在可以使用Suit.type.diamonds而不是SuitType.instance。diamonds,或者Suit.type.clubs而不是SuitType.instance.clubs
在Swift中,枚举类型可以像EnumType一样访问。案例:
let tableView = UITableView(frame: self.view. view)UITableViewStyle.Plain)
大多数情况下,只有当您有几个选项可以使用,并且确切地知道在每个选项上要做什么时,才会使用枚举类型。
在处理枚举类型时,使用for-in结构没有太大意义。
你可以这样做,例如:
func sumNumbers(numbers : Int...) -> Int {
var sum = 0
for number in numbers{
sum += number
}
return sum
}
你可以试着像这样列举
enum Planet: String {
case Mercury
case Venus
case Earth
case Mars
static var enumerate: [Planet] {
var a: [Planet] = []
switch Planet.Mercury {
case .Mercury: a.append(.Mercury); fallthrough
case .Venus: a.append(.Venus); fallthrough
case .Earth: a.append(.Earth); fallthrough
case .Mars: a.append(.Mars)
}
return a
}
}
Planet.enumerate // [Mercury, Venus, Earth, Mars]
更新到Swift 2.2+
func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
var i = 0
return AnyGenerator {
let next = withUnsafePointer(&i) {
UnsafePointer<T>($0).memory
}
if next.hashValue == i {
i += 1
return next
} else {
return nil
}
}
}
它更新了Swift 2.2表单@Kametrixom的答案
Swift 3.0+(非常感谢@Philip)
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
var i = 0
return AnyIterator {
let next = withUnsafePointer(&i) {
UnsafePointer<T>($0).pointee
}
if next.hashValue == i {
i += 1
return next
} else {
return nil
}
}
}
我在比特和字节中跌跌撞撞,创建了一个扩展,后来我发现它与@rintaro的答案非常相似。它是这样使用的:
enum E : EnumCollection {
case A, B, C
}
Array(E.cases()) // [A, B, C]
值得注意的是,它可以在任何没有关联值的enum上使用。注意,这对于没有大小写的枚举不起作用。
与@rintaro的答案一样,这段代码使用枚举的底层表示。这种表示没有文档化,将来可能会改变,这会破坏它。我不建议在生产中使用这种方法。
代码(Swift 2.2, Xcode 7.3.1,不工作在Xcode 10):
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func cases() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyGenerator<S> in
var raw = 0
return AnyGenerator {
let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
代码(Swift 3, Xcode 8.1,不工作在Xcode 10):
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func cases() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyIterator<S> in
var raw = 0
return AnyIterator {
let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
我不知道为什么我需要typealias,但编译器抱怨没有它。