#swift3
#swift3
Вопрос:
Я новичок в swift, затем хочу написать подсчет ИМТ.
Ошибка Не удается присвоить значение типа ‘Double’ ‘String?’
появляется в label.text = GetBMI(H: myH, W: myW)
Как я могу это исправить?
@IBAction func calBMI(_ sender: AnyObject) {
if Height.text != nil amp;amp; 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)
}
Ответ №1:
Вы можете найти несколько потоков, описывающих, как исправить Не удается присвоить значение типа ‘Double’ для ‘String?’, Но, к сожалению, эти потоки могут не указывать на некоторые плохие части вашего кода.
Если бы я исправил все такие части:
@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)
}
Некоторые моменты:
- Имена свойств должны представлять функцию содержимого. В вашем коде вы используете
height
иweight
в качествеDouble
значений, поэтому вам лучше назватьUITextField
s (предполагаяHeight
, что иWeight
являютсяUITextField
s ) чем-то другим. Я переименовал их вheightField
иweightField
. - Тестирование с
!= nil
использованием и последующее применение принудительной развертки (!
) не является предпочтительным способом, вам лучше избегать использования!
как можно больше. Лучше использовать необязательную привязку —if-let
. - Вы не должны использовать
(... as AnyObject).doubleValue
для преобразованияString
вDouble
. Вы можете использовать инициализаторDouble
для преобразованияString
вDouble
(# 1). Который возвращаетOptional<Double>
, поэтому лучше включите ихif-let
. - Вы не можете напрямую присвоить
Double
значение свойству типаString?
. Вы можете использовать инициализаторString
для преобразованияDouble
вString
(# 1). - В Swift вы обычно используете идентификатор с заглавной буквы только для типов, поэтому я переименовал
GetBMI(H:W:)
вgetBMI(h:w:)
.
(#1) Использование инициализаторов при преобразовании между String
и Double
является своего рода упрощенным способом. Этого может быть достаточно для создания учебного кода калькулятора BMI, но может быть недостаточно для реальных приложений. Рассмотрите возможность использования NSNumberFormatter
для реальных приложений.
Жирные линии обязательны или настоятельно рекомендуются.
Ответ №2:
label.text = String(GetBMI(H: myH, W: myW))
Ваша функция возвращает значение double, label.text будет принимать только строку. Следовательно, вы получаете сообщение об ошибке: невозможно присвоить значение типа ‘Double’ ‘String?.
Вопросительный знак в ошибке мог бы сбить вас с толку. Что? на ‘String?’ есть, потому что label.text МОЖЕТ быть пустым, поэтому его ‘необязательный’ ie: может иметь или не иметь значение. Противоположность ! который явно объявляет, что существует значение и равно != nil.