I am trying to pass data from textfield, back to previous controller using delegation. I am stuck when I try to assign Int value in this call.
This problem is fairly easy, however I cannot find a simple solution. I have been trying different approaches with additional properties that should hold this value, but with no succeed. What do I have to do with this budgetAmount.text to be properly converted?
protocol BudgetDelegate: class {
func enteredBudgetData(info: String, info2: Int)
}
class AddBudgetViewController: UIViewController {
var budget: Budget?
weak var delegate: BudgetDelegate? = nil
#IBOutlet weak var budgetName: UITextField!
#IBOutlet weak var budgetAmount: UITextField!
//
#IBAction func saveContent(_ sender: UIButton) {
if ((budgetName.text?.isEmpty)! && (budgetAmount.text?.isEmpty)!) {
navigationController?.pop(animated: true)
} else {
-> delegate?.enteredBudgetData(info: budgetName.text!, info2: budgetAmount.text!)
navigationController?.pop(animated: true)
}
}
}
Error Cannot convert value of type 'String' to expected argument type 'Int'
The info2 parameter of your protocol method is of type Int but you are passing budgetAmount.text! which is of course a String. You need to pass an Int.
Perhaps you need to convert the text in the textfield to an Int.
delegate?.enteredBudgetData(info: budgetName.text!, info2: Int(budgetAmount.text!) ?? 0)
BTW - you are making several terrible uses of the ! operator. You should spend time learning about optionals and how to safely work with then.
So based on your question, you just want to pass an Int data coming from a UITextField. And based on your description, you do not have any problem with delegation.
Converting a String into an Int is easy:
Example:
let num = "1"
if let intNum = Int(num) {
// There you have your Integer.
}
Related
Here's what I have so far:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var game1: UITextField!
#IBOutlet weak var game2: UITextField!
#IBOutlet weak var game3: UITextField!
#IBOutlet weak var series: UILabel!
#IBOutlet weak var average: UILabel!
#IBOutlet weak var high: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func calculate(_ sender: Any) {
let game1Results = Int(game1.text!)
let game2Results = Int(game2.text!)
let game3Results = Int(game3.text!)
let gameResultsArray = [game1Results, game2Results, game3Results]
high.text = "\(gameResultsArray.max())"
}
}
I've been trying to use the .max function but I'm getting errors stating I need to refer to conform to "Comparable". I'm pretty new to swift, any help will be much appreciated.
It happens because you try to compare values of optional Int (Int?)
First of all, you should know that not each String can be converted to an Int
E.g. '42' will be converted correctly, but 'ie42zx' can't be converted to and Int - that's why Int(String) function returns optional Int (Int?)
'Optional' property says like 'i can have a value, but I can also be nil'. That's why you should unwrap optionals in your code
First, I suggest to avoid force unwraping here.
let game1Results = Int(game1.text!)
It can be done like that:
guard
let text1 = game1.text,
let text2 = game2.text,
let text3 = game3.text
else { return }
You should do that because not every text field contains text, so textField.text property returns an optional String?
Then you can convert your String results to an Int and unwrap these results before compare:
guard
let game1Results = Int(text1),
let game2Results = Int(text2),
let game3Results = Int(text3)
else { return }
I would suggest to read more about optionals in swift and unwrapping (see Optionals paragraph)
I believe your issue is that the Int constructor with a string returns an optional integer value. You're trying to take the max of a bunch of optionals, so it cant figure it out.
You can use the compactMap function on your array before calling max() to filter out the nil values.
gameResultsArray.compactMap{ $0 }.max()
Yes, another found nil while unwrapping an Optional value error. I have read tons of other stack overflow posts with similar errors such as this one and many others. I still do not fully understand how to properly deal with unwrapping a variable.
I have a class that is similar to the following:
#IBOutlet weak var nameTextField: UITextField?
#IBOutlet weak var valueInput: UITextField?
var checkbox : CheckBox?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let name = nameTextField.text ?? ""
let state = buttonState.getIsChecked()
let value : Int? = Int(valueInput.text!)
let isMoveable = true
checkbox = CheckBox(name: name, value: value, state: state, isMoveable: isMoveable)
}
I get the error on the line the "let value : Int? = Int(valueInput.text!) line.
You can safely unwrap the value using if let construct
var value : Int? = nil
if let val = valueInput.text {
value = Int(val) // it would either nil or optional value
}
and also you can do it by nil coalescing operator ?? in a single line
let value : Int? = Int(valueInput.text ?? "")
UPDATE
First check if textfields disconnected from the Interface Builder , if not connect, connect them. and if you become your textfields optionals you also have to safely unwrap the textfields ( you forgot to add it from interface builder and it will not crash if you make them optionals).
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var name: String? = nil
var value : Int? = nil
let state = buttonState.getIsChecked()
let isMoveable = true
if let nameTextField = self.nameTextField where nameTextField.text != nil {
name = nameTextField.text!
}
if let valueTextField = self.valueInput where valueTextField.text != nil {
value = Int(valueTextField.text!)
}
checkbox = CheckBox(name: name, value: value, state: state, isMoveable: isMoveable)
}
Sahil's answer is on track, but doesn't address that valueInput is also an optional. Use this code:
if let valueInput = valueInput,
let val = valueInput.text {
value = Int(val)
}
In addition regarding properly unwrapping the optional valueInput I wanted to add that chances are that if valueInput is an IBOutlet it's defined as:
#IBOutlet weak var valueInput: UITextField!
That's called an implicitly unwrapped optional. The annoying thing is that since it is also an IBOutlet, if it ever becomes disconnected from the UITextField in Interface Builder, the variable will become nil, and accessing it from anywhere in the code will cause a crash.
Change it to this:
#IBOutlet weak var valueInput: UITextField?
I've also written about this on my blog: http://cleanswifter.com/implicitly-unwrapped-iboutlets/
Note: you didn't show the definition of valueInput so I assumed it to be a UITextField
I am new to swift, so apologies for funny question, but I am quite tanged in this optional type and the unwrapping thing.
So, I am trying to create a calculator for which I have a UITextField to display the digits while pressed or result after calculation and off course some buttons representing digits.
Now I have action methods attached which my digit buttons and return button properly.
I have my UITextField declared like following which is implicitly unwrapped and a mutable string array which is also unwrapped-
#IBOutlet weak var displayTextField: UITextField!
var digitArray : [String]!
The append digit method works fine which just take the digit from the button and displays it in the textfield by appending. But I am getting a Bad Access error in the enter method. I guess, I am trying to add the item in the array improperly. Can anyone please help.
#IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
displayTextField.text = digit + displayTextField.text
}
#IBAction func enter(sender: UIButton) {
digitArray.append(displayTextField.text)
}
digitArray is declared but not initialized.
var digitArray = [String]()
The initializer syntax is either a pair of parentheses after the type let x = Type() or in case of an array with the type annotation and a pair of square brackets let x : [Type] = [].
As the compiler infers the type, the declaration [String] is not needed.
Declare variables non optional whenever possible, you will get more and better help by the compiler.
Convert initializer to
var digitArray = [String]()
I am fiddling around with table views and I am stuck with the error Cannot assign a value of type 'Answer' to a value of type '[Answer]'
Answer is a class with the following definition:
class Answer {
var EnglishAnswer: String = ""
var ChineseAnswer: String = ""
init(newEng: String, newChi: String){
self.EnglishAnswer = newEng
self.ChineseAnswer = newChi
}
}
And I am running into problems in the prepareforsegue method:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexpath: NSIndexPath = self.tableView.indexPathForSelectedRow!
var DestinationViewController = segue.destinationViewController as! AnswerTableViewController
var ArrayofArrayswithAnswerElementsTwo : Answer
var ArrayofArrayswithAnswerElements = levelsArray.map( { $0.AnswersArray })
ArrayofArrayswithAnswerElementsTwo = ArrayofArrayswithAnswerElements[indexpath.row]
DestinationViewController.ArrayofArrayswithAnswerElements = ArrayofArrayswithAnswerElementsTwo
}
Error clearly stats that you are trying to assign array of Answer objects to a variable which is declared to hold only Answer objects.
This variable is meant to hold Answer object:
var ArrayofArrayswithAnswerElementsTwo : Answer
And I suspect this line is retuning an array of Answer objects:
ArrayofArrayswithAnswerElementsTwo = ArrayofArrayswithAnswerElements[indexpath.row]
You would need to put a breakpoint, check your model, print objects and check the right assignments in your prepareForSegue function.
Solution: There could be 2 solutions to your problem:
First, define ArrayofArrayswithAnswerElementsTwo like this
var ArrayofArrayswithAnswerElementsTwo : [Answer]
Second, make ArrayofArrayswithAnswerElements[indexpath.row] to return Answer and not [Answer]
PS: Naming convention of your variables is off sync with industry practice. Variable names should start with lower case and should be kept as short as possible.
Alright, so I'm building an app that takes in a sequence of int values using a text field and encrypts it depending upon the initialized cipher. Originally I use the .toInt() function to covert my numerical string values into an array of integer. Then I add the cipher to each value in the array of integers however I'm having difficulty outputting the int array back to the text-field with the encrypted sequence. I have already thoroughly researched this and I can't seem to find an adequate function to convert my int array (named: code) back into a string which I can initialize as message1.text = the string numerical sequence.
Here is my code so far:
class ViewController: UIViewController {
#IBOutlet var text: UITextField!
#IBOutlet var Lable: UILabel!
#IBOutlet var Button: UIButton!
#IBOutlet var message1: UITextField!
#IBOutlet var Button2: UIButton!
var name = 0
#IBAction func Button(sender: UIButton) {
name = text.text.toInt()!
}
#IBAction func Button2(sender: UIButton) {
var code = Array (message1.text).map{String($0).toInt()! }
for var n = 0 ; n < code.count; n++
{
code[n] = code[n] + name
}
var StringArray = (code : String()) // This is the mistake, I want to convert the code array into a joint string,
message1.text = StringArray
}
I already know that what I attempted to do doesn't work cause when I run the app and press Button2 I'am left with no text at all in the text-field thus it is a legitimate statement that String array is not being initialized as expected.
Any help is much appreciated, Thank you for your time I'm starting off in app programming and I'm still struggling at relatively simple stuff so I understand if the answer might seem overly palpable.
All you need to do is remap the values back to strings and join them:
var stringOfCodes = "".join( code.map { "\($0)" } )
This gives you a single string from the code values. I feel like there is a more elegant way to accomplish this, but this is what immediately came to mind.
If you want to create a string out of an array:
var spaceSeparatedString = " ".join(StringArray)
This will create a string out of the array using a space as the separator. Eg: "string1 string2 string3".