This question already has answers here:
Swift: adding optionals Ints
(7 answers)
Closed 4 years ago.
I am trying to make an application that allows you to save a number in UserDefaults and then add onto that number later on. Right now, I keep getting the error:
'Binary operator '+' cannot be applied to two 'Int?' operands'
Can anyone point me in the right direction?
class FirstViewController: UIViewController {
var totalHoursInt = 0
var typeHoursInt = 0
var savedHours = 0
#IBOutlet weak var totalHours: UILabel!
#IBOutlet weak var typeHours: UITextField!
#IBAction func addButton(_ sender: Any) {
totalHours.text = typeHours.text!
UserDefaults.standard.set(typeHours.text, forKey: "savedHours")
typeHours.text = ""
var totalHoursInt = Int(totalHours.text!)
var typeHoursInt = Int(typeHours.text!)
print(totalHoursInt + typeHoursInt)
}
override func viewDidAppear(_ animated: Bool) {
if let x = UserDefaults.standard.object(forKey: "savedHours") as? String {
totalHours.text = x
}
}
}
Int() with a String argument doesn’t return an Int value but an Int Optional. This is because the String to Int conversion could fail in which case the conversion returns nil. And the + operator simply isn’t defined for optionals.
To solve your problem you will need to make sure the returned values aren in-nil, using a construct like this:
if let totalHours = totalHoursInt, let typeHours = typeHoursInt {
print(totalHours + typeHours)
}
if let ... assigns a value only if the right side is non-nil so the variables are converted from optionals to non-optionals. (You’re using that in viewDidAppear.) After that, the + operator will work.
Related
I want to accept user input in a range, but keep on getting error:
Cannot convert value of type Range<Int32> to expected argument type Range<_>
I am learning Swift but I did not understand the different scenarios to convert UITextField to text and maybe integer.
class ViewController: UIViewController {
#IBOutlet weak var Range1: UITextField!
#IBOutlet weak var Range2: UITextField!
#IBOutlet weak var TheNUmber: UITextField!
#IBOutlet weak var OutletLabel: UILabel!
#IBAction func Guess(_ sender: UIButton) {
var R1 = (Range1.text! as NSString).intValue
var R2 = (Range2.text! as NSString).intValue
//print(R1, " ", R2)
var answer = Int.random(in: R1..<R2)
// I tried my best to use custom range from UItext field but did not work.
//I need more help.
print ("Random Number: \(answer)")
var turn = 0;
if(((R1>1)&&(R1<1000))&&((R2>1)&&(R2<1000))){
for i in 1...5{
let guess = (TheNUmber.text! as NSString).intValue
turn = i;
//let guess = (TheNUmber.text! as NSString).intValue
if(guess == answer){
OutletLabel.text = ("Yes, it is \(answer).")
OutletLabel.text = ("It took you \(turn) tries.")
break
}
else if(guess>answer){
OutletLabel.text = ("Lower!")
}
else if (guess<answer){
OutletLabel.text = ("Higher!")
}
else{
continue;
}
}
if (turn > 5){
OutletLabel.text = ("Sorry, it was \(answer).")
}
}
else{
OutletLabel.text = ("Keep the numbers between 1 and 100.")
}
}
#IBAction func Reset(_ sender: Any) {
self.Reset (sender)
}
I am not sure about this error. Please help me with the range.
The problem is that intValue returns an Int32, not an Int. So change
var R1 = (Range1.text! as NSString).intValue
var R2 = (Range2.text! as NSString).intValue
var answer = Int.random(in: R1..<R2)
To
let R1 = Int((Range1.text! as NSString).intValue)
let R2 = Int((Range2.text! as NSString).intValue)
let answer = Int.random(in: R1..<R2)
Even better, don't use NSString or intValue. Use Swift.
let R1 = Int(Range1.text!)!
let R2 = Int(Range1.text!)!
let answer = Int.random(in: R1..<R2)
Be aware that this code can crash — for example, if the user types "howdy" instead of an integer. But you need to deal with that.
Your code has other issues, but at least you will get past this one.
Just starting learning swift but stuck when trying to multiply an input with another number and display on a label. I get the error that the number isn't a string and tried to cast but didn't work.
class ViewController: UIViewController {
#IBOutlet weak var entry: UITextField!
#IBOutlet weak var answer: UILabel!
#IBAction func button(_ sender: Any) {
answer.text = entry.text * 2
}
}
You should cast the text into a Double, an Int etc., then convert the calculation to a string.
if let entry = Double(entry.text) {
answer.text = "\(entry * 2)"
}
or
if let entry = Int(entry.text) {
answer.text = "\(entry * 2)"
}
If you know that the entry will hold a number
answer.text = String(Int(entry.text)! * 2)
Using optional unwrapping instead
if let num = Int(entry.text) {
answer.text = String(num * 2)
}
I am unable to fix this issue, I'm using Xcode6.
var numbersOnscreen:Double = 0;
#IBOutlet var displabel: UILabel!
#IBAction func numbers(sender: UIButton) {
displabel.text = displabel.text + String(sender.tag-1)
numbersOnscreen = Double(displabel.text) //error line
}
Try this:
numbersOnscreen = Double(displabel.text!)!
The init method you were calling expects a String (not an optional string):
struct Double {
init?(_ text: String) { ... }
}
And keep in mind this is a failable initializer so another unwrapping (i.e., the last !) is needed as well.
I'm learning Swift right now, and in the course we have a lesson to make a simple app. Now I'm having problems with some text fields programming that it's not working properly.
Here is my code:
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField?
#IBOutlet weak var felicidadeField: UITextField?
#IBAction func addRefeicao(sender: UIButton) {
if refeicaoField == nil || felicidadeField == nil {
return
}
let nomeRefeicao = refeicaoField!.text
let valorFelicidade = felicidadeField!.text
let valorFelicidadeInt = Int(valorFelicidade!)
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
}
}
The problem starts here:
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
Where it says: value of optional 'Int?' not unwrapped; did you mean to use '!' or '?' and also value of optional 'String?' not unwrapped; did you mean to use '!' or '?'
I'm little confused, because in the lesson example they have done like this:
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt!)
And worked, but for me no. And if I try to put '!' at the two variables, I have an exclamation warning prompting no use for let novaRefeicao.
What's wrong?
EDIT:
Done some changes using all the tips found here, now my code is like:
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField!
#IBOutlet weak var felicidadeField: UITextField!
#IBAction func addRefeicao(sender: UIButton) {
if refeicaoField == nil || felicidadeField == nil {
return
}
let nomeRefeicao = refeicaoField!.text
let valorFelicidade = felicidadeField!.text
if nomeRefeicao == nil {
return
}
if let valorFelicidadeInt = Int(valorFelicidade!) {
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
} else {
return
}
}
}
Now I receive the error on unwrapped again, but now with the "nomeRefeicao" instead. Tried to put the '!' in it, but then it shows that let novaRefeicao is immutable value.
You should understand that the Swift language has changed a lot over the past year and that exclamation point has moved quite a bit over time. If your examples are from even mid-2015, you're looking at out-dated syntax.
Having a value with ? means that this item may contain a value... or it may not.
Having a value with ! means that you are forcibly unwrapping an object which can be rather dangerous, use it sparingly and only when you know for certain that it will not cause a crash.
If you have an optional value, you can safely unwrap it like this:
guard let unwrapped = wrapped else {
return
}
or
if let unwrapped = wrapped {
print(unwrapped)
}
A little more info, if you have an initialized optional value, what you've really got is this:
enum Optional<A> {
case None
case Some(A)
}
This is why you cannot use your value without unwrapping it... it's 'wrapped' in an optional enum that either has a value or doesn't.
Your code with a little safeguard added:
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField?
#IBOutlet weak var felicidadeField: UITextField?
#IBAction func addRefeicao(sender: UIButton) {
guard let refeicaoField = refeicaoField!.text else {
return
}
guard let felicidadeField = felicidadeField!.text else {
return
}
let nomeRefeicao = refeicaoField ?? "error" // added protection
let valorFelicidade = felicidadeField ?? "error" // added protection
let valorFelicidadeInt = Int(valorFelicidade) ?? 0 // defaults to '0' in case of issue
}
}
Both the text property of UITextField and the result of the Int(string:String) initializer return an optional value.
So you have to unwrap both in case the method expects non optional parameters.
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao!, alegriaEmComer: valorFelicidadeInt!)
The most compact syntax is
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField!
#IBOutlet weak var felicidadeField: UITextField!
#IBAction func addRefeicao(sender: UIButton) {
if let nomeRefeicao = refeicaoField.text, valorFelicidade = felicidadeField.text, valorFelicidadeInt = Int(valorFelicidade) {
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
// do something with novaRefeicao
}
}
}
The Meal initializer is only called if
refeicaoField.text is not nil
felicidadeField.text is not nil and can be converted to Int
There is no need to check the UITextField instances for nil.
If you get a runtime error, one of the fields is not connected in IB.
The message Initialization of immutable value ... is a warning, because the created Meal instance assigned to novaRefeicao is never used. That's why I added the comment line do something …
The line:
let valorFelicidadeInt = Int(valorFelicidade!)
converts a String value into an Int. What should your code do if the string cannot be converted to an integer? You need to address that explicitly.
In Swift, the conversion has a type of Optional - either the conversion worked or it did not. You thus have two cases to cover. The following is a possible approach:
if let valorFelicidadeInt = Int(valorFelicidade!) {
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
// continue using `Meal`
}
else {
// User error; text not an int
}
The if let will succeed if Int(...) returns a non-nil optional; you'll then build the Meal.
The same approach to unwrapping by handling the two options applies to other parts of your code.
I am having problems with calling the function in Swift, when building an iOS app.
#IBOutlet weak var vyseHypoteky: UITextField!
#IBOutlet weak var dobaSplaceni: UITextField!
#IBOutlet weak var urokovaSazba: UITextField!
#IBOutlet weak var mesicniSplatka: UITextField!
#IBAction func zmenaVyseHypoteky(sender: UISlider) {
var currentValue = Int(sender.value)
vyseHypoteky.text = "\(currentValue)"
vypoctiSplatku()
}
#IBAction func zmenaDobySplaceni(sender: UISlider) {
var currentValue = Int(sender.value)
dobaSplaceni.text = "\(currentValue)"
}
#IBAction func zmenaUrokoveSazby(sender: UISlider) {
var currentValue = Int(sender.value)
urokovaSazba.text = "\(currentValue)"
}
func vypoctiSplatku () {
let HU:Int? = vyseHypoteky.text.toInt()
let ipa:Int? = urokovaSazba.text.toInt()
let n:Int? = dobaSplaceni.text.toInt()
var ipm = ipa! / 12
var zavorka = 1+ipm
var vypoctenaZavorka = mocnina(mocnenec: zavorka, mocnitel: n)
var citatel = HU! * ipm * vypoctenaZavorka
var jmenovatel = vypoctenaZavorka - 1
var splatka = citatel / jmenovatel
mesicniSplatka.text = ("\splatka")
}
func mocnina (mocnenec: Int, mocnitel: Int) -> Int {
var mocnina = 1
for _ in 1...mocnitel {
mocnina *= mocnenec
}
return mocnina
}
The app is calculating a number by my formula. I want to use my function to calculate the x^y, this the "mocnina" function where I want to use two int, the x is "mocnenec" and the y is "mocnitel".
And finally I want to send the final int from variable "splatka" to text inout filed "mesicniSplatka".
But I am getting errors in calling the function "mocnina" --> var vypoctenaZavorka = mocnina(mocnenec: zavorka, mocnitel: n)
Extraneous argument label 'mocnenec:' in call
Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
and in the end with mesicniSplatka.text = ("\splatka")
Invalid escape sequence in literal
How to fix it? Thx for helping a total newbie :)
The problem is that n is a wrapped:
var n:Int?
So you have a few options, you can either change your code to unwrap it when you use it (probably a good idea to check for nil before doing this as this will cause an exception if n is nil):
var vypoctenaZavorka = mocnina(mocnenec: zavorka, mocnitel: n!)
Or you can unwrap it when you create it:
let n:Int = dobaSplaceni.text.toInt()!
If you'd like to better understand "when to use optionals", I've written a very long explanation to this question on the subject: UIViewController variables initialization
In your code, n is declared of type Int?, it means "Optional Int". This is normal because the toInt() function is not guaranteed to succeed, and might return nil if the text is not convertible to an integer. So, you need to unwrap it first, like this: var vypoctenaZavorka = mocnina(mocnenec: zavorka, mocnitel: n!). Or, if you're not sure the conversion from string succeeded, do something like this:
let HU:Int? = vyseHypoteky.text.toInt()
let ipa:Int? = urokovaSazba.text.toInt()
let n:Int? = dobaSplaceni.text.toInt()
if ipa != nil {
var ipm = ipa! / 12
var zavorka = 1+ipm
if n != nil {
var vypoctenaZavorka = mocnina(mocnenec: zavorka, mocnitel: n)
// etc...
}
}