Why is Swift creating optional parameter without '?'
Question
While trying to implement the "experiment" on page 35 of the Swift programming guide I get a very strange error in the Xcode playground. In the pokerDeck
method, on the line beginning with let card...
in the innermost loop, I get the error Value of optional type 'Rank?' not unwrapped
. How/why is Rank
optional?
struct Card {
var rank : Rank
var suit : Suit
init(rank : Rank, suit : Suit) {
self.rank = rank
self.suit = suit
}
func pokerDeck() -> Card[] {
let suits = [Suit.Spades, Suit.Clubs, Suit.Hearts, Suit.Diamonds]
var deck = Card[]()
for suit in suits {
for r in 1 ... 13 {
let card = Card(rank: Rank.fromRaw(r), suit: suit) // ERROR
deck += card
}
}
return deck
}
}
The suggested fix by Xcode is to add a !
let card = Card(rank: Rank.fromRaw(r)!, suit: suit)
Which makes the problem even murkier.
Solution
The fromRaw()
method of an Enum doesn't know what you will pass to it – it can't know if it will succeed on every call – so they designed that method with a return type of Rank?
(the return type is an optional)
the !
operator (known as forced unwrapping) forces an optional to be converted into an Enum (and will cause an error if it is nil
)
OTHER TIPS
Your problem is that fromRaw returns an optional value. The suggested fix is correct if you're sure all raw values you pass will have an enum value.
the fromRaw() method of an enum returns an optional of the type because there is no guarantee that there is a value for every raw value.
In swift, certain functions return optional wrapped types. In this case, the fromRaw() function returns an optional wrapped enum.
When you know that the type will always be present, declare the var with an exclamation mark (!). This will automatically unwrap the optional to either be used as desired or a runtime error if nil.