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)
}
结果示例:
♠
♥
♦
♣
当前回答
我创建了一个实用函数iterateEnum(),用于迭代任意枚举类型的情况。
下面是示例用法:
enum Suit: String {
case Spades = "♠"
case Hearts = "♥"
case Diamonds = "♦"
case Clubs = "♣"
}
for f in iterateEnum(Suit) {
println(f.rawValue)
}
输出:
♠
♥
♦
♣
但是,这仅用于调试或测试目的:这依赖于几个未记录的Swift1.1编译器行为,因此,使用它的风险由您自己承担。
代码如下:
func iterateEnum<T: Hashable>(_: T.Type) -> GeneratorOf<T> {
var cast: (Int -> T)!
switch sizeof(T) {
case 0: return GeneratorOf(GeneratorOfOne(unsafeBitCast((), T.self)))
case 1: cast = { unsafeBitCast(UInt8(truncatingBitPattern: $0), T.self) }
case 2: cast = { unsafeBitCast(UInt16(truncatingBitPattern: $0), T.self) }
case 4: cast = { unsafeBitCast(UInt32(truncatingBitPattern: $0), T.self) }
case 8: cast = { unsafeBitCast(UInt64($0), T.self) }
default: fatalError("cannot be here")
}
var i = 0
return GeneratorOf {
let next = cast(i)
return next.hashValue == i++ ? next : nil
}
}
其基本思想是:
枚举的内存表示,不包括有关联类型的枚举,只是一个案例的索引,当案例的计数是2…256,它和UInt8是一样的,当257…65536,它是UInt16等等。因此,它可以是unsafeBitcast对应的无符号整数类型。 枚举值的. hashvalue与case的索引相同。 从无效索引位转换的枚举值的. hashvalue为0。
为Swift2修改,并从@Kametrixom的回答中实现了选角想法:
func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> {
var i = 0
return anyGenerator {
let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
return next.hashValue == i++ ? next : nil
}
}
对Swift3的修订:
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
var i = 0
return AnyIterator {
let next = withUnsafePointer(to: &i) {
$0.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee }
}
if next.hashValue != i { return nil }
i += 1
return next
}
}
针对Swift3.0.1修订:
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
var i = 0
return AnyIterator {
let next = withUnsafeBytes(of: &i) { $0.load(as: T.self) }
if next.hashValue != i { return nil }
i += 1
return next
}
}
其他回答
在Swift 3中,当底层枚举有rawValue时,你可以实现Strideable协议。优点是不像其他建议那样创建值数组,并且标准的Swift“for in”循环工作,这是一个很好的语法。
// "Int" to get rawValue, and Strideable so we can iterate
enum MyColorEnum: Int, Strideable {
case Red
case Green
case Blue
case Black
// required by Strideable
typealias Stride = Int
func advanced(by n:Stride) -> MyColorEnum {
var next = self.rawValue + n
if next > MyColorEnum.Black.rawValue {
next = MyColorEnum.Black.rawValue
}
return MyColorEnum(rawValue: next)!
}
func distance(to other: MyColorEnum) -> Int {
return other.rawValue - self.rawValue
}
// just for printing
func simpleDescription() -> String {
switch self {
case .Red: return "Red"
case .Green: return "Green"
case .Blue: return "Blue"
case .Black: return "Black"
}
}
}
// this is how you use it:
for i in MyColorEnum.Red ... MyColorEnum.Black {
print("ENUM: \(i)")
}
在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
}
在处理Swift 2.0时,以下是我的建议:
我已经将原始类型添加到Suit enum
enum Suit: Int {
然后:
struct Card {
var rank: Rank
var suit: Suit
func fullDeck()-> [Card] {
var deck = [Card]()
for i in Rank.Ace.rawValue...Rank.King.rawValue {
for j in Suit.Spades.rawValue...Suit.Clubs.rawValue {
deck.append(Card(rank:Rank(rawValue: i)! , suit: Suit(rawValue: j)!))
}
}
return deck
}
}
如果你给枚举一个原始的Int值,它将使循环更容易。
例如,你可以使用anyGenerator来获得一个可以枚举你的值的生成器:
enum Suit: Int, CustomStringConvertible {
case Spades, Hearts, Diamonds, Clubs
var description: String {
switch self {
case .Spades: return "Spades"
case .Hearts: return "Hearts"
case .Diamonds: return "Diamonds"
case .Clubs: return "Clubs"
}
}
static func enumerate() -> AnyGenerator<Suit> {
var nextIndex = Spades.rawValue
return anyGenerator { Suit(rawValue: nextIndex++) }
}
}
// You can now use it like this:
for suit in Suit.enumerate() {
suit.description
}
// or like this:
let allSuits: [Suit] = Array(Suit.enumerate())
然而,这看起来像一个相当常见的模式,如果我们可以通过简单地遵循协议使任何枚举类型可枚举,这不是很好吗?有了Swift 2.0和协议扩展,现在我们可以了!
简单地添加到你的项目:
protocol EnumerableEnum {
init?(rawValue: Int)
static func firstValue() -> Int
}
extension EnumerableEnum {
static func enumerate() -> AnyGenerator<Self> {
var nextIndex = firstRawValue()
return anyGenerator { Self(rawValue: nextIndex++) }
}
static func firstRawValue() -> Int { return 0 }
}
现在,任何时候你创建一个枚举(只要它有一个Int原始值),你可以通过遵循协议使它可枚举:
enum Rank: Int, EnumerableEnum {
case Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
}
// ...
for rank in Rank.enumerate() { ... }
如果你的枚举值不以0开头(默认值),重写firstRawValue方法:
enum DeckColor: Int, EnumerableEnum {
case Red = 10, Blue, Black
static func firstRawValue() -> Int { return Red.rawValue }
}
// ...
let colors = Array(DeckColor.enumerate())
最后一个Suit类,包括用更标准的CustomStringConvertible协议替换simpleDescription,看起来像这样:
enum Suit: Int, CustomStringConvertible, EnumerableEnum {
case Spades, Hearts, Diamonds, Clubs
var description: String {
switch self {
case .Spades: return "Spades"
case .Hearts: return "Hearts"
case .Diamonds: return "Diamonds"
case .Clubs: return "Clubs"
}
}
}
// ...
for suit in Suit.enumerate() {
print(suit.description)
}
Swift 3语法:
protocol EnumerableEnum {
init?(rawValue: Int)
static func firstRawValue() -> Int
}
extension EnumerableEnum {
static func enumerate() -> AnyIterator<Self> {
var nextIndex = firstRawValue()
let iterator: AnyIterator<Self> = AnyIterator {
defer { nextIndex = nextIndex + 1 }
return Self(rawValue: nextIndex)
}
return iterator
}
static func firstRawValue() -> Int {
return 0
}
}
Xcode 10与Swift 4.2
enum Filter: String, CaseIterable {
case salary = "Salary"
case experience = "Experience"
case technology = "Technology"
case unutilized = "Unutilized"
case unutilizedHV = "Unutilized High Value"
static let allValues = Filter.allCases.map { $0.rawValue }
}
叫它
print(Filter.allValues)
打印:
[“薪酬”、“经验”、“技术”、“未利用”、“未利用的高价值”]
旧版本
对于表示Int的enum
enum Filter: Int {
case salary
case experience
case technology
case unutilized
case unutilizedHV
static let allRawValues = salary.rawValue...unutilizedHV.rawValue // First to last case
static let allValues = allRawValues.map { Filter(rawValue: $0)!.rawValue }
}
这样叫它:
print(Filter.allValues)
打印:
[0, 1, 2, 3, 4]
用于表示字符串的enum
enum Filter: Int {
case salary
case experience
case technology
case unutilized
case unutilizedHV
static let allRawValues = salary.rawValue...unutilizedHV.rawValue // First to last case
static let allValues = allRawValues.map { Filter(rawValue: $0)!.description }
}
extension Filter: CustomStringConvertible {
var description: String {
switch self {
case .salary: return "Salary"
case .experience: return "Experience"
case .technology: return "Technology"
case .unutilized: return "Unutilized"
case .unutilizedHV: return "Unutilized High Value"
}
}
}
叫它
print(Filter.allValues)
打印:
[“薪酬”、“经验”、“技术”、“未利用”、“未利用的高价值”]