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)
}
结果示例:
♠
♥
♦
♣
当前回答
Swift 4 + 2。
从Swift 4.2 (Xcode 10)开始,只需将协议一致性添加到CaseIterable中,就可以从allCases中受益。要添加这个协议一致性,你只需要在某个地方写:
extension Suit: CaseIterable {}
如果枚举是你自己的,你可以直接在声明中指定一致性:
enum Suit: String, CaseIterable { case spades = "♠"; case hearts = "♥"; case diamonds = "♦"; case clubs = "♣" }
然后下面的代码将打印所有可能的值:
Suit.allCases.forEach {
print($0.rawValue)
}
与早期Swift版本的兼容性(3。X和4.x)
如果您需要支持Swift 3。x或4.0,你可以通过添加以下代码来模仿Swift 4.2的实现:
#if !swift(>=4.2)
public protocol CaseIterable {
associatedtype AllCases: Collection where AllCases.Element == Self
static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
static var allCases: [Self] {
return [Self](AnySequence { () -> AnyIterator<Self> in
var raw = 0
var first: Self?
return AnyIterator {
let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
if raw == 0 {
first = current
} else if current == first {
return nil
}
raw += 1
return current
}
})
}
}
#endif
其他回答
enum Rank: Int
{
case Ace = 0
case Two, Three, Four, Five, Six, Seve, Eight, Nine, Ten
case Jack, Queen, King
case Count
}
enum Suit : Int
{
case Spades = 0
case Hearts, Diamonds, Clubs
case Count
}
struct Card
{
var rank:Rank
var suit:Suit
}
class Test
{
func makeDeck() -> Card[]
{
let suitsCount:Int = Suit.Count.toRaw()
let rankCount:Int = Rank.Count.toRaw()
let repeatedCard:Card = Card(rank:Rank.Ace, suit:Suit.Spades)
let deck:Card[] = Card[](count:suitsCount*rankCount, repeatedValue:repeatedCard)
for i:Int in 0..rankCount
{
for j:Int in 0..suitsCount
{
deck[i*suitsCount+j] = Card(rank: Rank.fromRaw(i)!, suit: Suit.fromRaw(j)!)
}
}
return deck
}
}
根据Rick的回答:这要快5倍
我发现自己在代码中经常使用. allvalues。我终于找到了一种方法来简单地遵循Iteratable协议并拥有一个rawValues()方法。
protocol Iteratable {}
extension RawRepresentable where Self: RawRepresentable {
static 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
}
}
}
extension Iteratable where Self: RawRepresentable, Self: Hashable {
static func hashValues() -> AnyIterator<Self> {
return iterateEnum(self)
}
static func rawValues() -> [Self.RawValue] {
return hashValues().map({$0.rawValue})
}
}
// Example
enum Grocery: String, Iteratable {
case Kroger = "kroger"
case HEB = "h.e.b."
case Randalls = "randalls"
}
let groceryHashes = Grocery.hashValues() // AnyIterator<Grocery>
let groceryRawValues = Grocery.rawValues() // ["kroger", "h.e.b.", "randalls"]
在处理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
}
}
在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)")
}
(改进Karthik Kumar的回答)
这个解决方案是使用编译器来保证你不会错过一个case。
enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
static var enumerate: [Suit] {
switch Suit.spades {
// make sure the two lines are identical ^_^
case .spades, .hearts, .diamonds, .clubs:
return [.spades, .hearts, .diamonds, .clubs]
}
}
}