I am trying to set up questions with a text field for answers. Only after the exact answer has been entered can the next question be shown. I'm getting an error code with "if answerField == answers[currentQuestionIndex]" I believe I need to have allowances for what can be entered as answers. I'm stuck and could use some help in the right direction. thank you
#IBAction func answerField(sender: AnyObject) {
for index in 1...5 {
if answerField == answers[currentQuestionIndex] {
++self.currentQuestionIndex
if self.currentQuestionIndex == self.questions.count {
self.currentQuestionIndex = 0
}
}
}
}
let questions: [String] = ["From what is cognac made?", "What is 7+7?", "What is the capital of Vermont?"]
let answers: [String] = ["Grapes", "14", "Montpelier"]
override func viewDidLoad() {
super.viewDidLoad()
currentQuestion.text = questions[currentQuestionIndex]
}
answerField as you've shown it here is not a UITextField; it is a function. That is what the error is telling you: A function that takes AnyObject as a parameter and returns nothing ((AnyObject)->()) can't be compared to a String.
I think perhaps what you wanted to do was create an outlet (not an action) for your answer field:
#IBOutlet weak var answerField: UITextField! // Make sure you actually hook this up to your text field in the storyboard.
Then, listen for changes to the content of the text field:
override func viewDidLoad()
{
super.viewDidLoad()
answerField.addTarget(
self,
action: #selector(answerChanged(_:)),
forControlEvents: .EditingChanged)
currentQuestion.text = questions[currentQuestionIndex]
}
And then handle changes to your answer field text:
func answerChanged(sender: AnyObject)
{
if (answerField.text ?? "") == answers[currentQuestionIndex]
{
currentQuestionIndex = currentQuestionIndex + 1 < questions.count ? currentQuestionIndex + 1 : 0
currentQuestion.text = questions[currentQuestionIndex]
}
}
Or something along those lines.
If you answerField variable is UIText field then you need to use its text. The is an optional property so you also need to unwrap it
if (answerField.text ?? "") == answers[currentQuestionIndex]
From error code mentioned seems like you don't have variable answerField and you are trying to compare function itself to String, that doesn't make any sense
Related
I'm new to Swift. I managed to build an app which almost works, but I cannot get the last steps right. I would appreciate any help!
I wrote a code which displays a user-defined number of UILabels. In those labels, the contents of a [String] is displayed. Under the labels, there is the same number of UITextFields. The user should fill out these text fields, press the button and then see if what he filled out matches the labels.
All the labels, the text fields, and the button are made completely programmatically, so without using the storyboard. In the viewDidLoad there is all the code and this line:
myButton.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
Right under viewDidLoad there is this function which I found on this forum and I changed it a bit:
#objc func buttonAction(sender: UIButton!) -> [String] {
var a = 0
var userInput: [String] = Array()
while a < 4 {
if let myTextField = self.view.viewWithTag(a) as? UITextField {
let tekstInput = myTextField.text
userInput.insert(tekstInput!, at:a-1)
}
a = a + 1
}
return userInput
}
My problems:
The while-loop in the function shouldn't have 4 as the maximum, but a user-defined variable. But if I try to change function so that it expects that variable as an input, I get error messages in the myButton.addTarget line.
How do I read out the return in the viewdidload to add there the code to compare the user input with the original [String]?
You should consider the source of the user-defined input if you want to answer your question.
For instance, if you are willing to add an extra UITextField to retrieve your user input, then all you have to do is extract the value from that text field within your buttonAction(sender:) method and use it there. This translates roughly to the following
#objc func buttonAction(_ sender: UIButton) {
var a = 0
var userInput: [String] = Array()
guard let upperLimit = self.userInputTextField.text as? Int else {
return
}
while a < upperLimit {
if let myTextField = self.view.viewWithTag(a) as? UITextField {
let tekstInput = myTextField.text
userInput.insert(tekstInput!, at: a-1)
}
a = a + 1
}
}
Note that self.userInputTextField is the extra text field you should add in order to retrieve your user-defined input.
i'm new the forum and also new to the swift language. I've been playing around with xcode and wanted to create an app that uses a fenceloop to display the factors of a number as a "solution." The app currently uses a label to display, a text for input, and a button to initiate. I have what i think to be functioning code but i can't see to get it to work because from what i understand, i have to convert the input that's a string into an int. If anyone has any ideas how to get this working; since i feel like i've done what i can.
The problem in particular i am getting is it is saying that "Cannot convert value of type 'UITextField!; to expected argument type 'Int'. What i intend to happen is that on the button click, it solves for the factors of whatever is in the text box and displays it as a string in the label. Any help is appreciated!
import UIKit
class ViewController: UIViewController {
#IBOutlet var input1 : UITextField!
#IBOutlet var label : UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func printFactors(n: Int) {
var result: String = ""
for i in 1...n {
guard n % i == 0 else {continue}
result += i == 1 ? "1" : " and \(i)"
}
print(result)
let outputText = printFactors(n: input1)
label.text = outputText
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You have a lot of issues and confusion in your printFactors method. Lets split it up and setup things properly.
First, make a separate method to do the math:
func calculateFactors(n: Int) -> String {
var result: String = ""
for i in 1...n {
guard n % i == 0 else {continue}
result += i == 1 ? "1" : " and \(i)"
}
print(result)
return result
}
Now lets setup the button action:
#IBAction func factorAction(sender: UIButton) {
if let text = input1.text {
if let num = Int(text) {
let factor = calculateFactors(n: num)
label.text = factor
} else {
// Show the user that the entered text isn't a number
}
} else {
// There's no text
}
}
Setup your button to use the new factoryAction: method instead of the old printFactors: method.
Swift 3
Can reduce this code down to two lines with some functional magic.
func factors(of number: Int) -> [Int] {
return (1...number).filter { number % $0 == 0 }
}
print(factors(of: 24))
I want to display a String in a separate function and just call the function when the user choose the wrong answer, the problem is when I create the function and I try to use it my app crash and is telling me an error about the index is out of range..... any suggestion how can I fix this? or a recommendation to do a better and clean job? Here is my code:
//This is my struct
struct Question {
var Question: String!
var Answers: [String]!
var Answer: Int!
var Img: UIImage!
var Info: String!
}
override func viewDidLoad() {
super.viewDidLoad()
//Here the way I display the questions
questions = [
Question(
Question: "Question #1",
Answers: ["A","B","C","D"],
Answer: 1,
Img: UIImage.self(named: "steve"),
Info: "Steve"
),
]
//Here is my function that I want to create to display the Info:
private function showInformation() {
infoLabel.text = questions[Question].Info
}
Ps: If need more details let me know, by the way my function to create a random question is this
private func pickingRandomQuestion() {
if questions.count > 0 {
questionNumber = random() % questions.count //This make a random pick of Question
questionLabel.text = questions[questionNumber].Question //Converting quesitonLabel into TEXT
answerNumber = questions[questionNumber].Answer
imgDisplay.image = questions[questionNumber].Img
//Im trying to use one of this examples to display but is not working :(
answerA.setTitle(questions[questionNumber].Answers[0], forState: .Normal)
answerB.setTitle(questions[questionNumber].Answers[1], forState: .Normal)
answerC.setTitle(questions[questionNumber].Answers[2], forState: .Normal)
answerD.setTitle(questions[questionNumber].Answers[3], forState: .Normal)
questions.removeAtIndex(questionNumber)
} else {
finishGame.hidden = false
answerA.hidden = true
answerB.hidden = true
answerC.hidden = true
answerD.hidden = true
}
}
You need to store your question's info in a property before you remove the question from the array of questions.
Add a property to your class:
var questionInfo = ""
In pickingRandomQuestion set the value before calling removeAtIndex:
questionInfo = questions[questionNumber].Info
Then use the property value in showInformation:
private function showInformation() {
infoLabel.text = questionInfo
}
This question already has an answer here:
Input from UITextField connected from storyboard to Swift view controller file
(1 answer)
Closed 6 years ago.
How can I take an input value from the user with a text field and then use it to perform math functions in Swift?
I want to get a value from the user and then find the sine of that value.
Plus I want to take the input and covert it into radians.
Please help.
According to your comment, you have the textfield as an IBOutlet. I've added a button to get the value:
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var label: UILabel!
#IBAction func buttonPress(sender: AnyObject) {
guard let text = textField.text, value = Double(text) else { return }
label.text = String(sin(value))
}
The reason I've used guard is because if text is nil or if it's not a Double, it will just return, having done nothing (which is what I want). This way you don't have to worry about unexpected crashes when trying to calculate the value.
let sinValue = sin(Double("2")!)
is how you would process the string into a sin value
To get the text from the text field, you would need something like:
let sinValue = sin(Double(someTextField.text)!)
but you would first want to check that the text field had a value and validate that it was a number to prevent a crash.
//Initialize Textfied
var textField = UITextField(frame: CGRect(0, 0, 100, 100))
var sinNumber:Double = 0
//Now in your header (where it says class X:subclass list)
//maybe something like class Viewcontroller:UIViewController, UITextFieldDelegate
Add UITextFieldDelegate as above
Then you need to add the following function to determine when the user is done editing their TextField
func textFieldDidEndEditing(textField: UITextField) {
sinNumber = getSinOfInput(textField.text)
}
func getSinOfNumber(numbers:String) {
//If numbers is NOT a string full of numbers (it has characters), it should return nil
var num = Double(numbers)
if num != nil {
//Do login here to find the sin
num = ....
return num
}
else {
return 0
}
}
Hi I just picked up Swift and am following the Stanford open course. I was making this calculator and got a breakpoint at the line of userIsInTheMiddleOfTyping = false in the func enter part when I placed the line before operandStack.append(displayValue). After I placed the line at the bottom of the function, the problem was solved. But why?
Also, I don't get the part of get and set in displayValue part. Can anyone help to explain how this part is executed. And where is the newValue from? why does it represent whatever value on the display? The code is followed. I would appreciate any answers and comments!
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTypingAnNumber = false
#IBAction func AppendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTypingAnNumber {
display.text = display.text! + digit
}
else{
display.text = digit
userIsInTheMiddleOfTypingAnNumber = true
}
}
var operandStack = Array<Double>()
#IBAction func enter() {
operandStack.append(displayValue)
println("operandStack=\(operandStack)")
userIsInTheMiddleOfTypingAnNumber = false
}
var displayValue: Double{
get{
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set{
display.text = "\(newValue)"
userIsInTheMiddleOfTypingAnNumber = false
}
}
}
get and set are the keywords used in Swift to define custom getters and setters to a property.
newValue is the default name for the new value that will be assigned to the variable at the end of the setter, it allows you to check various things before assigning it.
For the first part of your question I don't quite understand what's not working for you.