Reputation: 35
I'am a swift beginner then want to write a BMI counting.
A error Cannot assign value of type 'Double' to 'String?'
appear in label.text = GetBMI(H: myH, W: myW)
How can I fix it ?
@IBAction func calBMI(_ sender: AnyObject) {
if Height.text != nil && Weight.text != nil {
let myH : Double = (Height.text! as AnyObject).doubleValue
let myW : Double = (Weight.text! as AnyObject).doubleValue
label.text = GetBMI(H: myH, W: myW)
}
else {
label.text = "Please enter your Height and Weight!"
}
}
func GetBMI(H: Double, W: Double) -> Double {
let height: Double = H / 100
return W / (height * height)
}
Upvotes: 0
Views: 3661
Reputation: 193
label.text = String(GetBMI(H: myH, W: myW))
Your function returns a double, the label.text will only accept a string. Hence the error message you get: Cannot assign value of type 'Double' to 'String?.
The question mark in the error might of thrown you off. The ? on 'String?' is there because the label.text MIGHT be empty, so its an 'optional' ie: may or may not have a value. Opposite of ! which explicitly declares there is a value and is != nil.
Upvotes: 1
Reputation: 47886
You can find some threads describing how to fix Cannot assign value of type 'Double' to 'String?', but unfortunately those threads may not point out some bad parts of your code.
If I were to fix all such parts:
@IBOutlet var heightField: UITextField! //Renamed `Height` to `heightField`
@IBOutlet var weightField: UITextField! //Renamed `Weight` to `weightField`
@IBAction func calBMI(_ sender: AnyObject) {
if //Optional binding (using `if-let`) is the more preferred way than `!= nil` and forced unwrapping.
let heightText = heightField.text,
let weightText = weightField.text,
//You should not use `(... as AnyObject).doubleValue` to convert `String` to `Double`
//and should check if the text values are valid representation of Double
let myH = Double(heightText),
let myW = Double(weightText)
{
//This is the key point for the error "Cannot assign value of type 'Double' to 'String?'"
label.text = String(getBMI(h: myH, w: myW)) //You need to convert `Double` to `String`
}
else {
label.text = "Please enter your Height and Weight!"
}
}
//Renamed `GetBMI(H:W:)` to `getBMI(h:w:)`
func getBMI(h: Double, w: Double) -> Double {
let height: Double = h / 100
return w / (height * height)
}
Some points:
Property names should represent the content's feature. In your code, you use height
and weight
as Double
values, so you'd better name UITextField
s (assuming Height
and Weight
are UITextField
s) with something other. I renamed them to heightField
and weightField
.
Testing with != nil
and then applying forced unwrapping (!
) is not a preferred way, you'd better avoid using !
as much as possible. Better use Optional binding -- if-let
.
You should not use (... as AnyObject).doubleValue
to convert String
to Double
. You can use the initializer of Double
to convert String
to Double
(#1). Which returns Optional<Double>
, so better include them in if-let
.
You cannot directly assign Double
value to a property of type String?
. You can use the initializer of String
to convert Double
to String
(#1).
In Swift, you usually use capitalized identifier only for types, so I renamed GetBMI(H:W:)
to getBMI(h:w:)
.
(#1) Using initializers when converting between String
and Double
is sort of a simplified way. It may be sufficient for making a BMI Calculator tutorial code, but may not be sufficient for actual apps. Consider using NSNumberFormatter
for actual apps.
Bold lines are mandatory or strongly recommended.
Upvotes: 4