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)
}
结果示例:
♠
♥
♦
♣
当前回答
实验内容是: 实验
在Card中添加一个方法,用于创建一副完整的牌,每一副牌都是rank和花色的组合。
因此,除了添加方法之外,没有修改或增强给定的代码(并且没有使用还没有教过的东西),我想出了这个解决方案:
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
func createDeck() -> [Card] {
var deck: [Card] = []
for rank in Rank.Ace.rawValue...Rank.King.rawValue {
for suit in Suit.Spades.rawValue...Suit.Clubs.rawValue {
let card = Card(rank: Rank(rawValue: rank)!, suit: Suit(rawValue: suit)!)
//println(card.simpleDescription())
deck += [card]
}
}
return deck
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
let deck = threeOfSpades.createDeck()
其他回答
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 {
...
static let ranks = (Rank.Ace.rawValue ... Rank.King.rawValue).map{Rank(rawValue: $0)! }
}
enum Suit {
...
static let suits = [Spades, Hearts, Diamonds, Clubs]
}
struct Card {
...
static func fullDesk() -> [Card] {
var desk: [Card] = []
for suit in Suit.suits {
for rank in Rank.ranks {
desk.append(Card(rank: rank,suit: suit))
}
}
return desk
}
}
这个怎么样?
有一种聪明的方法,尽管令人沮丧,但它说明了两种不同类型的枚举之间的区别。
试试这个:
func makeDeck() -> Card[] {
var deck: Card[] = []
var suits: Suit[] = [.Hearts, .Diamonds, .Clubs, .Spades]
for i in 1...13 {
for suit in suits {
deck += Card(rank: Rank.fromRaw(i)!, suit: suit)
}
}
return deck
}
交易是,一个由数字(原始值)支持的枚举是隐式显式有序的,而一个没有数字支持的枚举是显式隐式无序的。
例如,当我们给枚举值数字时,语言足够狡猾,可以找出数字的顺序。 另一方面,如果我们不给它任何顺序,当我们尝试迭代这些值时,语言就会举起双手说:“是的,但你想先执行哪个??”
其他可以做到这一点(迭代无序枚举)的语言可能是相同的语言,其中所有内容实际上都是一个地图或字典,你可以迭代地图的键,无论是否有任何逻辑顺序。
诀窍是给它提供一些显式排序的东西,在这个例子中,suit的实例在数组中按照我们想要的顺序。一旦你这么说,霉霉就会说“你为什么不一开始就这么说呢?”
另一个简写技巧是在fromRaw函数上使用强制操作符。这说明了关于枚举的另一个“陷阱”,即可能传入的值的范围通常大于枚举的范围。例如,如果我们说Rank.fromRaw(60),就不会返回值,所以我们使用了语言的可选特性,在我们开始使用可选特性的地方,很快就会出现强制。(或者交替if let结构,这对我来说仍然有点奇怪)
这看起来像一个黑客,但如果你使用原始值,你可以这样做
enum Suit: Int {
case Spades = 0, Hearts, Diamonds, Clubs
...
}
var suitIndex = 0
while var suit = Suit.fromRaw(suitIndex++) {
...
}
这是一个相当老的帖子,来自Swift 2.0。现在有一些更好的解决方案,使用了swift 3.0的新特性: 在Swift 3.0中迭代一个Enum
关于这个问题,有一个解决方案,它使用了Swift 4.2的一个新功能(在我写这篇编辑时还没有发布): 我如何得到一个Swift枚举的计数?
在这个帖子中有很多好的解决方案,但其中一些非常复杂。我喜欢尽可能地简化。这里有一个解决方案,可能适用于不同的需求,但我认为它在大多数情况下都很好:
enum Number: String {
case One
case Two
case Three
case Four
case EndIndex
func nextCase () -> Number
{
switch self {
case .One:
return .Two
case .Two:
return .Three
case .Three:
return .Four
case .Four:
return .EndIndex
/*
Add all additional cases above
*/
case .EndIndex:
return .EndIndex
}
}
static var allValues: [String] {
var array: [String] = Array()
var number = Number.One
while number != Number.EndIndex {
array.append(number.rawValue)
number = number.nextCase()
}
return array
}
}
迭代:
for item in Number.allValues {
print("number is: \(item)")
}