Reputation: 671
I'm currently working on teaching myself Swift programming and am encountering an error message that I do not know how to get rid of. The error message reads:
warning: expression implicitly coerced from 'String?' to Any
From my understand this warning message is due to the fact that the print() function that I'm calling in my code expects an argument of the type 'Any' and is instead being passed an argument of the type 'String', but I'm not sure about how to go about suppressing or preventing this error or message. My program is a simple Magic 8 Ball command line program:
import Foundation
// Greet user, and then prompt he or she to ask his or her question
print("Welcome to Magic 8 Ball!")
print("What is your question? ")
var question = readLine()!
// Initialize a dictionary named 'answer', this array will contain all 20 of the
// standard Magic 8 Ball responses.
let answer = ["zero": "It is certain.",
"one": "It is decidedly so.",
"two": "Without a doubt.",
"three": "Yes, definitely.",
"four": "You may rely on it.",
"five": "As I see it, yes.",
"six": "Most likely.",
"seven": "Outlook good.",
"eight": "Yes.",
"nine": "Signs point to yes.",
"ten": "Reply hazy, try again.",
"eleven": "Ask again later.",
"twelve": "Better not tell you now.",
"thirteen": "Cannot predict now.",
"fourteen": "Concentrate and ask again.",
"fifteen": "Don't count on it.",
"sixteen": "My reply is no.",
"seventeen": "My sources say no.",
"eightteen": "Outlook not so good.",
"nineteen": "Very doubtful."]
// Generate a random number between 0 and 19.
// We will use this number to choose chick answer to show the user
var randomUInt32:UInt32 = arc4random_uniform(20)
// Convert UInt32 datatype to Int
var randomInt: Int = Int(randomUInt32)
switch (randomInt) {
case 0:
print(answer["zero"]) // tell fortune
case 1:
print(answer["one"]) // tell fortune
case 2:
print(answer["two"]) // tell fortune
case 3:
print(answer["three"]) // tell fortune
case 4:
print(answer["four"]) // tell fortune
case 5:
print(answer["five"]) // tell fortune
case 6:
print(answer["six"]) // tell fortune
case 7:
print(answer["seven"]) // tell fortune
case 8:
print(answer["eight"]) // tell fortune
case 9:
print(answer["nine"]) // tell fortune
case 10:
print(answer["ten"]) // tell fortune
case 11:
print(answer["eleven"]) // tell fortune
case 12:
print(answer["twelve"]) // tell fortune
case 13:
print(answer["thirteen"]) // tell fortune
case 14:
print(answer["fourteen"]) // tell fortune
case 15:
print(answer["fifteen"]) // tell fortune
case 16:
print(answer["sixteen"]) // tell fortune
case 17:
print(answer["seventeen"]) // tell fortune
case 18:
print(answer["eightteen"]) // tell fortune
case 19:
print(answer["nineteen"]) // tell fortune
default:
print("ERROR: PC LOAD LETTER") // tell fortune
}
Program Output:
Optional("Yes, definitely.")
NOTE: I know that a dictionary isn't a great choice for this particular program, but I'm working through a book on Swift so I'm just messing around with all of the different data types and data structures as I work through the book.
Upvotes: 0
Views: 1428
Reputation: 61
You can think of two ways to achieve this:
1)
case 0:
print(String(answer["zero"]!))
You can use it like this. [Using force unwrap concept you can achieve your goal] but I would suggest going with the optional approach as it will not break your code.
2)
case 0:
print(String(answer["zero1"] ?? "Error"))
By mistakenly, you wrote 'zero1' instead of 'zero', and you used 'String(answer["zero1"]!)'. In that case, it will break your code, so it's good to use optionals.
Upvotes: 0
Reputation: 671
I happened to figure out the solution after taking a small break. The solution simply involves 'unwrapping' the optional. The optionals in this case are answer["zero"]
through answer["nineteen"]
. So all that is needed to fix the bug is to add the !
operator to the optional and the code will run without warnings. Example: answer["zero"]!
. Here is my code with the bug fix:
import Foundation
// Greet user, and then prompt he or she to ask his or her question
print("Welcome to Magic 8 Ball!")
print("What is your question? ")
var question = readLine()!
// Initialize a dictionary named 'answer', this array will contain all 20 of the
// standard Magic 8 Ball responses.
let answer = ["zero": "It is certain.",
"one": "It is decidedly so.",
"two": "Without a doubt.",
"three": "Yes, definitely.",
"four": "You may rely on it.",
"five": "As I see it, yes.",
"six": "Most likely.",
"seven": "Outlook good.",
"eight": "Yes.",
"nine": "Signs point to yes.",
"ten": "Reply hazy, try again.",
"eleven": "Ask again later.",
"twelve": "Better not tell you now.",
"thirteen": "Cannot predict now.",
"fourteen": "Concentrate and ask again.",
"fifteen": "Don't count on it.",
"sixteen": "My reply is no.",
"seventeen": "My sources say no.",
"eightteen": "Outlook not so good.",
"nineteen": "Very doubtful."]
// Generate a random number between 0 and 19.
// We will use this number to choose chick answer to show the user
var randomUInt32:UInt32 = arc4random_uniform(20)
// Convert UInt32 datatype to Int
var randomInt: Int = Int(randomUInt32)
// tell fortune
switch (randomInt) {
case 0:
print(String(answer["zero"]!))
case 1:
print(String(answer["one"]!))
case 2:
print(String(answer["two"]!))
case 3:
print(String(answer["three"]!))
case 4:
print(String(answer["four"]!))
case 5:
print(String(answer["five"]!))
case 6:
print(String(answer["six"]!))
case 7:
print(String(answer["seven"]!))
case 8:
print(String(answer["eight"]!))
case 9:
print(String(answer["nine"]!))
case 10:
print(String(answer["ten"]!))
case 11:
print(String(answer["eleven"]!))
case 12:
print(String(answer["twelve"]!))
case 13:
print(String(answer["thirteen"]!))
case 14:
print(String(answer["fourteen"]!))
case 15:
print(String(answer["fifteen"]!))
case 16:
print(String(answer["sixteen"]!))
case 17:
print(String(answer["seventeen"]!))
case 18:
print(String(answer["eightteen"]!))
case 19:
print(String(answer["nineteen"]!))
default:
print("ERROR: PC LOAD LETTER")
}
If anyone else happens to stumble upon this error message, I hope my post helps!
Upvotes: 1
Reputation: 63369
When you make a call like answer["one"]
, you're making a call to Dictionary.subscript(_:)
. This returns an optional (in this case, String?
, a.k.a. Optional<String>
) because as far as the compiler knows, there might not be a value for the given key ("one"
).
print
, formally known as print(_:separator:terminator:)
takes any number of Any
arguments. When you pass your String?
(the value subscripted from the dictionary), you're implicitly converting it to an Any
, which obscures the fact that the value is indeed optional. The warning is suggesting you make this explicit, if obscuring the optionality is really what you want (e.g. print(array["one"] as Any)
). By making it explicit like this, you're saying "Yes, I know this cast to Any
obscures the optionality, and that's what I want."
Your bigger problem is that this code needs major code review:
// Greet user, and then prompt he or she to ask his or her question
print("Welcome to Magic 8 Ball!")
clearly prints a greeting.print("What is your question?")
is clearly asking for a question.print(answer["four"]) // tell fortune
print("ERROR: PC LOAD LETTER") // tell fortune
"ERROR: PC LOAD LETTER"
is a strange fortune to tell.array
is actually a Dictionary<String, String>
(a.k.a. [String: String]
).Array<String>
(a.k.a. [String]
)!Here is how I would recommend implementing this:
import Foundation
let magic8BallAnswers = [
"It is certain.",
"It is decidedly so.",
"Without a doubt.",
"Yes, definitely.",
"You may rely on it.",
"As I see it, yes.",
"Most likely.",
"Outlook good.",
"Yes.",
"Signs point to yes.",
"Reply hazy, try again.",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Don't count on it.",
"My reply is no.",
"My sources say no.",
"Outlook not so good.",
"Very doubtful.",
]
extension Array {
func randomElement() -> Element? {
if self.isEmpty { return nil }
return self[Int(arc4random_uniform(UInt32(self.count)))]
}
}
print("Welcome to Magic 8 Ball!")
print("What is your question?")
var question = readLine()!
// Forceunwrap is justified here, because we know the array is not empty.
let answer = magic8BallAnswers.randomElement()!
print("Magic 8 Ball says: \(answer)")
Upvotes: 2