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)
}
结果示例:
♠
♥
♦
♣
当前回答
我发现了一种有点俗气但更安全的方法,它不需要键入两次值或引用枚举值的内存,因此不太可能损坏。
基本上,与其使用枚举,不如创建一个具有单个实例的结构体,并将所有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
其他回答
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倍
实验内容是: 实验
在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中,枚举类型可以像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
}
我的解决方案是声明一个包含所有枚举可能性的数组。所以for循环可以遍历所有这些。
//Function inside struct Card
static func generateFullDeck() -> [Card] {
let allRanks = [Rank.Ace, Rank.Two, Rank.Three, Rank.Four, Rank.Five, Rank.Six, Rank.Seven, Rank.Eight, Rank.Nine, Rank.Ten, Rank.Jack, Rank.Queen, Rank.King]
let allSuits = [Suit.Hearts, Suit.Diamonds, Suit.Clubs, Suit.Spades]
var myFullDeck: [Card] = []
for myRank in allRanks {
for mySuit in allSuits {
myFullDeck.append(Card(rank: myRank, suit: mySuit))
}
}
return myFullDeck
}
//actual use:
let aFullDeck = Card.generateFullDeck() //Generate the desired full deck
var allDesc: [String] = []
for aCard in aFullDeck {
println(aCard.simpleDescription()) //You'll see all the results in playground
}
对不起,我的回答是具体到我如何在我需要做的事情中使用这篇文章。对于那些无意中遇到这个问题的人,寻找一种方法在枚举中找到一个case,这是一种方法(Swift 2新增):
编辑:小写驼峰现在是Swift 3 enum值的标准
// From apple docs: If the raw-value type is specified as String and you don’t assign values to the cases explicitly, each unassigned case is implicitly assigned a string with the same text as the name of that case.
enum Theme: String
{
case white, blue, green, lavender, grey
}
func loadTheme(theme: String)
{
// this checks the string against the raw value of each enum case (note that the check could result in a nil value, since it's an optional, which is why we introduce the if/let block
if let testTheme = Theme(rawValue: theme)
{
// testTheme is guaranteed to have an enum value at this point
self.someOtherFunction(testTheme)
}
}
对于那些对枚举感到疑惑的人来说,本页上给出的答案包括一个包含所有枚举值的数组的静态var/let是正确的。最新的苹果tvOS示例代码包含了完全相同的技术。
也就是说,他们应该在语言中构建一个更方便的机制(苹果,你在听吗?)