im programming a calculator app as an exercise project.
I have already used the text of the label before via
calculatorLabel.text
Eventhough I use exactly the same expression in another function, I always get 0 instead of the actual text inside it. I seriously do not understand why that happens. I have already tried using debug mode and stuff but it doesn't work.
here ar the two functions (shortened):
#IBAction func operationButtonTapped(_ sender: UIButton) {
let operation = sender.currentTitle!
lastSender.backgroundColor = UIColor.systemBlue
lastSender = sender
sender.backgroundColor = UIColor.orange
//a switch would be here(deleted)
isTyping = false
let currentNumber = Double(calculatorLabel.text!)!
a = currentNumber
}
#IBAction func changeStateButtonTapped(_ sender: UIButton) {
let operation = sender.currentTitle!
let displayedNumber = Double(calculatorLabel.text!)!
var displayedText = self.calculatorLabel.text!
if operation == "+/-"{
if operation.prefix(1) == "-" {
displayedText.remove(at: displayedText.startIndex)
}
else{
displayedText = "-" + String(displayedNumber)
}
}
else if operation == "%"{
displayedText = String(displayedNumber/100)
}
calculatorLabel.text = displayedText
}
the top one gets the text while the bottom one doesn't...
thank you very much in advance for trying to help me!
I found the answer...
It seems the connection between it and the code was somehow messed up.
To all who have the same problem: right click the component in the storyboard and check the connections!
Related
Screen in question I am trying to call the viewDidLoad() func here with the question() func a set number of times and only then call the code for the new view controller to be pushed. But, the code for both is getting executed at the same exact time such that as soon as the first round finishes, the view controller is pushed. I have tried using loops in different variations, but those attempts all led to similar results. Ideas? And thanks in advance!
var num1 = Int()
var num2 = Int()
var userInput = 0
#IBAction func numbers(_ sender: UIButton) {
answerLabel.text = answerLabel.text! + String(sender.tag - 1)
userInput = Int(answerLabel.text!)!
answer()
}
override func viewDidLoad() {
super.viewDidLoad()
// Views configuration
question()
}
func answer() {
let answer = num1 + num2
if userInput == answer {
answerLabel.text = ""
viewDidLoad()
let scoreVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "ScoreViewController") as! ScoreViewController
self.navigationController?.pushViewController(scoreVC, animated: true)
}
}
func question() {
num1 = Int(arc4random_uniform(100))
num2 = Int(arc4random_uniform(100))
questionLabel.text = "\(num1) + \(num2)"
}
There are quit e few things that we can improve here. I'll start at basic.
As these numbers are unset at the beginning we don't have to assign them yet. So instead of settings them to a default value we can leave them as Optionals which allows us to just define the type and leave them be for an assignment later on.
var num1: Int?
var num2: Int?
Now we wanna show a Question. The thing is, the viewDidLoad shall only be used when - as the name suggests - the view loads. Because of this we simply create a Method and move our logic there. You already did that, I just renamed your function to a more speaking name
viewDidLoad() {
showNewQuestion()
}
showNewQuestion() { // previously question()
num1 = Int(arc4random_uniform(100))
num2 = Int(arc4random_uniform(100))
questionLabel.text = "\(num1) + \(num2)"
}
So far so good. Now we gotta check the input against the random value in the Button send function. Instead of force unwrapping (!) it is better practise to safely unwrap (?).
#IBAction func numbers(_ sender: UIButton) {
guard let userInput = answerLabel.text, let userInputAsInt = Int(userInput) else {
return
}
checkAnswer(userInput: userInputAsInt) // previously answere()
}
Lastly we improve your answer() function. The thing you left is to count how many questions have been answered. If we don't ever check that how should the program know when to show the score? To fix this problem we remember how many questions were asked (correctAnsweres ) and we define a threshold when to show the score (showScoreAfter)
var correctAnsweres = 0
var showScoreAfter = 5
func checkAnswer(userInputAsInt: Int) {
let answer = num1 + num2
if userInputAsInt != answers { // early exit if answered wrong
return
}
correctAnsweres += 1
answerLabel.text = ""
//either show score
if correctAnsweres % ShowScoreAfter == 0 {
let scoreVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "ScoreViewController") as! ScoreViewController
self.navigationController?.pushViewController(scoreVC, animated: true)
}
// or new Question
else {
showNewQuestion()
}
}
I am new to Swift and I am having issues with deleting a character from a UI Label that I have created. I am trying to make a simple phone dailer app, and I am trying ti implement a backspace button. My UI Label is called DailerLabel, and I know I'm supposed to use the dropLast() function but I keep running into issues about mismatching types or unwrappers. I am not really sure what I am supposed to do here. I tried the thing in the commented code which didn't work, and then I tried what I listed below which doesn't either. Could anyone help me?
#IBAction func backspaceButtonPressed(_ sender: UIButton) {
if (!((DailerLabel.text?.isEmpty)!)) {
// DailerLabel.text?.substring(to: (DailerLabel.text?.index(before: (DailerLabel.text?.endIndex)!))!)
let temp = DailerLabel.text
temp?.dropLast()
DailerLabel.text = temp
}
You can try this one, replace label with your own UILabel
var name: String = label.text! //shauket , for example
name.remove(at: name.index(before: name.endIndex))
print(name) //shauke
label.text = name
print(label.text!)
You are very close. dropLast actually returns the string without the last character and you haven't stored that to anything so there is no change. You also have to conver back to String from Substring.
#IBAction func backspaceButtonPressed(_ sender: UIButton) {
if (!((DailerLabel.text?.isEmpty)!)) {
let temp = DailerLabel.text ?? ""
DailerLabel.text = String(temp.dropLast())
}
}
Here's a better version
#IBAction func backspaceButtonPressed(_ sender: UIButton) {
guard
let text = dialerLabel.text,
!text.isEmpty
else {
return
}
dialerLabel.text = String(text.dropLast())
}
Please help and I'm sorry if this is covered somewhere else although i have looked elsewhere and whilst there are answers to my topic i cannot find one for my problem. so if anyone could help that would be great.
basically i am trying to do a switch statement inside a button so that when i click the button the statement activates in my label, but for some reason i cannot get it to work
here is my code below
when i hit run it always shows the "This is an even number between 0 and 10" regardless of even number, odd number or large number
Any help would be greatly appreciated
thank you very much
Right before the switch line you have to add three lines to assign the value of the input text field to the variable number.
guard let inputText = numberInput.text, let input = Int(inputText) else {
numberOutput.text = "Please enter a number!"
return }
number = input
This code works fine in playground, always prints expected output.
var number = 6
switch number {
case 0,2,4,6,8,10:
print("even")
case 1,3,5,7,9:
print("odd")
default:
print("higher")
}
where are you changing the number variable? Are you doing it on one of the callback methods for textfield delegate?
you are not changing the value of your var number. Looks like it is always 6 based from your code
You can simply do this:
import UIKit
class EmptyViewController: UIViewController
{
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textField: UITextField!
#IBAction func buttonHit(_ sender: UIButton)
{
if let text = textField.text, let number = Int(text)
{
switch number {
case 0,2,4,6,8,10:
label.text = "Even"
case 1,3,5,7,9:
label.text = "Odd"
default:
label.text = "Higher"
}
}
else
{
label.text = "Please enter a valid number"
}
}
}
I can't believe I'm having a problem with the very first lecture! We are building a calculator (it is not at all functional as a calculator at this point). Mine was working just fine until the performOperation function was added. Now I'm getting "this class is not key value coding compliant" error. The thing is that, as far as I can see, my code EXACTLY replicates the code that he is using in the class. I must be missing something but I've checked roughly 50 times to find a difference and I can't find one. Help? It is crashing every time.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTyping = false
#IBAction func touchDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTyping {
let textCurrentlyInDisplay = display.text!
display.text = textCurrentlyInDisplay + digit
} else {
display.text = digit
}
userIsInTheMiddleOfTyping = true
}
#IBAction func performOperation(sender: UIButton) {
userIsInTheMiddleOfTyping = false
if let mathematicalSymbol = sender.currentTitle {
if mathematicalSymbol == "π" {
display.text = String(M_PI)
}
}
}
}
EDIT: Code format
You can check your viewcontroller in storyboard, at the Module TextField in the right toolbar.
Do following steps if module textfield
is empty (there’s no placeholder):
Step 1. Focus Module TextField
Step 2. Edit randomly then clear
Step 3. Press Enter, if the result is as same as this picture, everything’s going okey.
(Swift)
So the problem is:
My app (which is a kind of calculator) is crashing when the user puts in the textfield things that can't be calculated.
For example, if he types " -4-.", the app won't be able to do the math.
So, a pattern must be followed.
The following characters are allowed: 1234567890.-
The minus sign can only be typed when it is the first character in the textfield and cannot be typed again.
The point can only be typed after a number, and cannot be typed again.
Well you would have to determine:
When the user clicks on a number/digit/character, you would have to do a:
//Goes at top of one of your classes
var decimalCount:Int = 0
//At location of tap for character
if(decimalCount < 1) {
textField.text += "."
decimalCount += 1
}
This ideology could be applied to "-" as well.
Some how i have understood your question. According to my assumption our task is to validate the input for proper math function.Ok here we go.
First of all declare a bool variable at top of your class
var isNonNumericCharactersAllowes = true
At first we need to make our textfield to respond according to user input.So add delegate to text field and add the following delegate method.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//1. To make sure that this is applicable to only particular textfield add tag.
if textField.tag == 1 {
let char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
//Helps to react only while typing and not while clearing text
if (isBackSpace != -92) {
let numbersOnly = NSCharacterSet(charactersInString: "1234567890")
let characterSetFromTextField = NSCharacterSet(charactersInString: string)
let Validate:Bool = numbersOnly .isSupersetOfSet(characterSetFromTextField)
if !Validate {
if isNonNumericCharactersAllowes {
isNonNumericCharactersAllowes = false
return true
}
return false
}
isNonNumericCharactersAllowes = true
}
}
return true
}
The above method stops unusual text entry's such as 0..012,--4,4++ etc..
Now while hitting calculate button we need to some validation.Add the following code in IBAction.
#IBAction func calculate(sender: AnyObject) {
let textContent:String!
textContent = textFieldTwo.text
var characterContainer = textContent.characters.map { String($0) }
let numbersOnly = NSCharacterSet(charactersInString: "1234567890")
let lastObjectOfString = NSCharacterSet(charactersInString: characterContainer.last!)
let Validate:Bool = numbersOnly .isSupersetOfSet(lastObjectOfString)
if !Validate {
characterContainer .removeLast()
textFieldTwo.text = characterContainer .joinWithSeparator("")
}
}
This above validation helps in removing things like 30+20+,4+4+, etc.. i.e removes unused operators at the end.