What am I missing when calculating? - ios

I am pretty new with programming but I am currently learning iOS. I have been trying to build a calculator but I have some problems. For instance, when I try to calculate 2 + 2, it shows me 5. Because when I press the second number (in this case 2) it makes it 3.
Can anyone help me to fix and understand the problem?
import UIKit
class ViewController: UIViewController {
var numberOnScreen:Double = 0
var previousNumber:Double = 0
var performingMath = false
var operation = 0
#IBOutlet weak var label: UILabel!
#IBAction func numbers(_ sender: UIButton)
{
if performingMath == true
{
label.text = String(sender.tag)
numberOnScreen = Double(label.text!)!
performingMath = false
}
else
{
label.text = label.text! + String(sender.tag-1)
numberOnScreen = Double(label.text!)!
}
}
#IBAction func buttons(_ sender: UIButton)
{
if label.text != "" && sender.tag != 11 && sender.tag != 16
{
previousNumber = Double(label.text!)!
if sender.tag == 12 {
label.text = "/"
}
else if sender.tag == 13 {
label.text = "*"
}
else if sender.tag == 14 {
label.text = "-"
}
else if sender.tag == 15 {
label.text = "+"
}
operation = sender.tag
performingMath = true
}
else if sender.tag == 16 {
if operation == 12 {
label.text = String(numberOnScreen / previousNumber)
}
else if operation == 13 {
label.text = String(numberOnScreen * previousNumber)
}
else if operation == 14 {
label.text = String(numberOnScreen - previousNumber)
}
else if operation == 15 {
label.text = String(numberOnScreen + previousNumber)
}
}
else if sender.tag == 11 {
label.text = ""
numberOnScreen = 0
previousNumber = 0
operation = 0
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}

Related

Making a calculator in Swift

My problem is that I can click and input multiple numbers for my first value but then after I used a math operator (ex. +,-,*,/) it only allows me to input a single value unlike the first time running it.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var Label: UILabel!
var secondNumber: Double = 0;
var firstNumber: Double = 0;
var performingMath = false
var operatorUsed = 0;
#IBAction func cleartext(_ sender: UIButton) {
Label.text = ""
performingMath = false
}
#IBAction func Numbers(_ sender: UIButton) {
if performingMath {
Label.text = String(sender.tag - 1)
secondNumber = Double(Label.text!)!
performingMath = true
} else {
Label.text = Label.text! + String(sender.tag - 1)
secondNumber = Double(Label.text!)!
}
}
#IBAction func Operators(_ sender: UIButton) {
if Label.text != " " && sender.tag != 11 {
firstNumber = Double(Label.text!)!
if sender.tag == 12 {
Label.text = "+"
} else if sender.tag == 13 {
Label.text = "-"
} else if sender.tag == 14 {
Label.text = "*"
} else if sender.tag == 15 {
Label.text = "/"
}
operatorUsed = sender.tag
performingMath = true
} else if sender.tag == 11 {
if operatorUsed == 12 {
Label.text = String(firstNumber + secondNumber)
}
if operatorUsed == 13 {
Label.text = String(firstNumber - secondNumber)
}
if operatorUsed == 14 {
Label.text = String(firstNumber * secondNumber)
}
if operatorUsed == 15 {
Label.text = String(firstNumber / secondNumber)
}
}
}
}
I expect the that I can input many values as possible after I used a math operator (ex. +-*/)
When you update the label's text when performingMath is true, you just assign the new value instead of adding the value to the existing one (see line 3)
#IBAction func Numbers(_ sender: UIButton) {
if performingMath {
Label.text = String(sender.tag - 1) // !! HERE !!
secondNumber = Double(Label.text!)!
performingMath = true
} else {
Label.text = Label.text! + String(sender.tag - 1)
secondNumber = Double(Label.text!)!
}
}
This should perform the same action as when performingMath is false, so you just need to update this line with:
Label.text = Label.text! + String(sender.tag - 1)

Add a decimal to calculator app swift 4

I need help where to add the decimal function in the following code? I found the same question that had the same code but the corrections did not work. Looking for any help here!
Here is my code:
#IBOutlet weak var label: UILabel!
#IBAction func numbers(_ sender: UIButton) {
if performingMath == true {
label.text = String(sender.tag-1)
numberOnScreen = Double(label.text!)!
performingMath = false
}
else {
label.text = label.text! + String(sender.tag-1)
numberOnScreen = Double(label.text!)!
}
}
#IBAction func buttons(_ sender: UIButton) {
if label.text != "" && sender.tag != 11 && sender.tag != 16{
previousNumber = Double(label.text!)!
if sender.tag == 12 { //Divide
label.text = "/";
}
}
There is more code below with the other func buttons (multiply, add, subtract, etc...)
I appreciate any help!
I would add another button for the decimal point. You would need to check that pressing a decimal point made sense. For example:
if label.text == "" {
// Decimal at the start means add a zero
label.text = "0."
} else if label.text.contains(".") {
// Don’t add another decimal point!
}
// To get number from label
if let number = Double(label.text) {
// Use the number here
}

Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeeaa26f48)

I have no clue what this error means
Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeeaa26f48)
which means I have no clue how to fix my code. Please help me. Here is my code below if you need it. If you need more code ask me please. I hope you guys can help me. Edit: I included all of my code. I hope you guys can use it and sorry for not defining the variables that were necessary for this question. Again I hope you guys can solve this.
var score = 0
var randomAmountOfTime = Double(arc4random_uniform(5) + 2)
var randomAmountOfTime2 = Double(arc4random_uniform(5) + 2)
var randomAmountOfTime3 = Double(arc4random_uniform(5) + 2)
var randomAmountOfTime4 = Double(arc4random_uniform(5) + 2)
var randomAmountOfTime5 = Double(arc4random_uniform(5) + 2)
override func viewDidLoad() {
super.viewDidLoad()
if X != nil {
X.text = ""
}
if Puppy5 != nil {
Puppy5.isHidden = true
}
if Puppy4 != nil {
Puppy4.isHidden = true
}
if Puppy3 != nil {
Puppy3.isHidden = true
}
if Puppy2 != nil {
Puppy2.isHidden = true
}
if Puppy1 != nil {
Puppy1.isHidden = true
}
score = 0
if Score != nil {
Score.text = "Score - \(score)"
}
loadingProcess()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBOutlet var Score: UILabel!
#IBOutlet var X: UILabel!
#IBOutlet var Puppy5: UIButton!
#IBAction func puppy5(_ sender: Any) {
Puppy5.isHidden = true
score += 1
Score.text = "Score - \(score)"
}
#IBOutlet var Puppy4: UIButton!
#IBAction func puppy4(_ sender: Any) {
Puppy4.isHidden = true
score += 1
Score.text = "Score - \(score)"
}
#IBOutlet var Puppy3: UIButton!
#IBAction func puppy3(_ sender: Any) {
Puppy3.isHidden = true
score += 1
Score.text = "Score - \(score)"
}
#IBOutlet var Puppy2: UIButton!
#IBAction func puppy2(_ sender: Any) {
Puppy2.isHidden = true
score += 1
Score.text = "Score - \(score)"
}
#IBOutlet var Puppy1: UIButton!
#IBAction func puppy1(_ sender: Any) {
Puppy1.isHidden = true
score += 1
Score.text = "Score - \(score)"
}
func loadingProcess() {
if self.Puppy1 != nil && self.Puppy1.isHidden == true {
let when = DispatchTime.now() + randomAmountOfTime
DispatchQueue.main.asyncAfter(deadline: when) {
self.Puppy1.isHidden = false
self.loadingProcess()
}
} else if self.Puppy1 != nil && self.Puppy1.isHidden == false {
let when = DispatchTime.now() + 3
DispatchQueue.main.asyncAfter(deadline: when) {
self.Puppy1.isHidden = true
if self.X.text == "X" {
self.X.text = "X X"
} else if self.X.text == "" {
self.X.text = "X"
} else if self.X.text == "X X" {
self.X.text = "X X X"
}
}
}
self.loadingProcess()
}
You're calling self.loadingProcess() recursively without any condition. This infinite loop is certainly causing the crash.

Swift 4 - Quiz App Random Questions

I'm a beginner to Swift and generally Xcode. Thank you in advance for your time and help :)
I am doing a Quiz App, and I try to have random questions... I have a function to generate random numbers that I tried to apply in viewDidLoad()... unfortunately I can not guess how to use that information in his variable "var currentQuestion = 0"
This is the code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
generateRandomNumber(0, 9, 10)
}
override func viewDidAppear(_ animated: Bool) {
newQuestion()
}
// Quiz//
let questions = ["Q1","Q2","Q3","Q4","Q5"]
let answers = [["A","2","3"],["B","2","3"],["C","2","3"],["D","2","3"],["E","2","3"]]
//Variables
var currentQuestion = 0
var rightAnswerPlacement:UInt32 = 0
//Generate Random Numbers
func generateRandomNumber(_ from:Int, _ to:Int, _ qut:Int?) -> [Int] {
var myRandomNumbers = [Int]() //All our generated numbers
var numberOfNumbers = qut //How many numbers to generate
let lower = UInt32(from) //Generate from this number..
let higher = UInt32(to+1) //To this one
if numberOfNumbers == nil || numberOfNumbers! > (to-from) + 1 {
numberOfNumbers = (to-from) + 1
}
while myRandomNumbers.count != numberOfNumbers {
let myNumber = arc4random_uniform(higher - lower) + lower
if !myRandomNumbers.contains(Int(myNumber)) {
myRandomNumbers.append(Int(myNumber))
}
}
return myRandomNumbers
}
//Label
#IBOutlet weak var lbl: UILabel!
//Button
#IBAction func action(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerPlacement)) {
print ("RIGHT!")
} else {
print ("WRONG!!!!!!")
}
if (currentQuestion != questions.count) {
newQuestion()
} else {
}
}
//Function that displays new question
func newQuestion() {
lbl.text = questions[currentQuestion]
rightAnswerPlacement = arc4random_uniform(3)+1
//Create a button
var button:UIButton = UIButton()
var x = 1
for i in 1...3 {
//Create a button
button = view.viewWithTag(i) as! UIButton
if (i == Int(rightAnswerPlacement)) {
button.setTitle(answers[currentQuestion][0], for: .normal)
} else {
button.setTitle(answers[currentQuestion][x], for: .normal)
x = 2
}
}
currentQuestion += 1
}
Any idea that how will be possible to resolve?
First you need to store the array of random questions that you generate (side note you appear to try to generate 10 random numbers but have only 5 questions).
Then instead of using the currentQuestion directly you use that to access the question in the array.
So change it to this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
questionArray = generateRandomNumber(0, 9, 10)
}
override func viewDidAppear(_ animated: Bool) {
newQuestion()
}
// Quiz//
let questions = ["Q1","Q2","Q3","Q4","Q5"]
let answers = [["A","2","3"],["B","2","3"],["C","2","3"],["D","2","3"],["E","2","3"]]
//Variables
var currentQuestion = 0
var rightAnswerPlacement:UInt32 = 0
var questionArray: [Int] = [] // Just an initial value
//Generate Random Numbers
func generateRandomNumber(_ from:Int, _ to:Int, _ qut:Int?) -> [Int] {
var myRandomNumbers = [Int]() //All our generated numbers
var numberOfNumbers = qut //How many numbers to generate
let lower = UInt32(from) //Generate from this number..
let higher = UInt32(to+1) //To this one
if numberOfNumbers == nil || numberOfNumbers! > (to-from) + 1 {
numberOfNumbers = (to-from) + 1
}
while myRandomNumbers.count != numberOfNumbers {
let myNumber = arc4random_uniform(higher - lower) + lower
if !myRandomNumbers.contains(Int(myNumber)) {
myRandomNumbers.append(Int(myNumber))
}
}
return myRandomNumbers
}
//Label
#IBOutlet weak var lbl: UILabel!
//Button
#IBAction func action(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerPlacement)) {
print ("RIGHT!")
} else {
print ("WRONG!!!!!!")
}
if (currentQuestion != questions.count) {
newQuestion()
} else {
}
}
//Function that displays new question
func newQuestion() {
lbl.text = questions[questionArray[currentQuestion]]
rightAnswerPlacement = arc4random_uniform(3)+1
//Create a button
var button:UIButton = UIButton()
var x = 1
for i in 1...3 {
//Create a button
button = view.viewWithTag(i) as! UIButton
if (i == Int(rightAnswerPlacement)) {
button.setTitle(answers[questionArray[currentQuestion]][0], for: .normal)
} else {
button.setTitle(answers[questionArray[currentQuestion]][x], for: .normal)
x = 2
}
}
currentQuestion += 1
}
(I think the code is correct but I'm currently running some tests in Xcode so can't check. If there is a problem leave a comment.)

Trigger action from another swift class

I'm making a TextField which takes a proper date only. Now when I'm using the text field delegate and action methods in the same ViewController class in which my UITextField is, it is working fine. But, I have to make it like a reusable component which can be used in any project by drag and drop. I have two files - MakeDate.swift and ViewController.swift
MakDate.swift --
import Foundation
import UIKit
class MakeDate: NSObject, UITextFieldDelegate {
var textField: UITextField!
var string: String!
var viewController: UIViewController!
let characterset = NSCharacterSet(charactersInString: "0123456789")
init?(textField: UITextField!) {
self.textField = textField
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
self.string = string
return true
}
func takeProperDateInput() {
textField.addTarget(textField, action: #selector(self.textChange(_:)), forControlEvents: .EditingChanged)
}
#IBAction func textChange(sender: UITextField) {
print("\(sender.text!)")
print("\(sender.text!) && \(self.string)")
if self.string == "" {
if sender.text?.characters.count == 2 {
let index = sender.text?.endIndex.advancedBy(-2)
sender.text = sender.text?.substringToIndex(index!)
}
else if sender.text?.characters.count == 5 {
let index = sender.text?.endIndex.advancedBy(-2)
sender.text = sender.text?.substringToIndex(index!)
}
}
if sender.text?.characters.count == 1 && self.string != "" {
if self.string.rangeOfCharacterFromSet(characterset.invertedSet) != nil {
let index = sender.text?.endIndex.advancedBy(-1)
sender.text = sender.text?.substringToIndex(index!)
}
else if Int(sender.text!) != 1 && Int(sender.text!) != 0 {
sender.text = "0" + sender.text! + "/"
}
}
else if sender.text?.characters.count == 2 && self.string != "" {
if Int(string) != 1 && Int(string) != 2 && Int(string) != 0{
let index = sender.text?.endIndex.advancedBy(-1)
sender.text = sender.text?.substringToIndex(index!)
}else {
sender.text = sender.text! + "/"
}
}
else if sender.text?.characters.count == 4 && self.string != "" {
if self.string.rangeOfCharacterFromSet(characterset.invertedSet) != nil {
let index = sender.text?.endIndex.advancedBy(-1)
sender.text = sender.text?.substringToIndex(index!)
}
}
else if sender.text?.characters.count == 5 && self.string != "" {
if self.string == "/" {
var yearComponent = sender.text?.componentsSeparatedByString("/")
let index = sender.text?.endIndex.advancedBy(-2)
sender.text = sender.text?.substringToIndex(index!)
sender.text = sender.text! + "0" + yearComponent![1] + "/"
}else {
var yearComponent = sender.text?.componentsSeparatedByString("/")
if Int(yearComponent![1]) > 31 {
let index = sender.text?.endIndex.advancedBy(-1)
sender.text = sender.text?.substringToIndex(index!)
}else if Int(yearComponent![1]) > 0 && Int(yearComponent![1]) < 32 {
sender.text = sender.text! + "/"
}else {
let index = sender.text?.endIndex.advancedBy(-1)
sender.text = sender.text?.substringToIndex(index!)
}
}
}
else if sender.text?.characters.count == 10 && self.string != "" {
let index = sender.text?.endIndex.advancedBy(-4)
if sender.text?.substringFromIndex(index!).rangeOfCharacterFromSet(characterset.invertedSet) != nil {
let index = sender.text?.endIndex.advancedBy(-4)
sender.text = sender.text?.substringToIndex(index!)
} else {
var yearComponent = sender.text?.componentsSeparatedByString("/")
if Int(yearComponent![2]) == 0 {
let index = sender.text?.endIndex.advancedBy(-4)
sender.text = sender.text?.substringToIndex(index!)
}
}
}
else if sender.text?.characters.count > 10 && self.string != "" {
let index = sender.text?.endIndex.advancedBy(-1)
sender.text = sender.text?.substringToIndex(index!)
}
}
}
and ViewController.swift --
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var dateInsert: UITextField!
var dateMaker: MakeDate!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
dateMaker = MakeDate(textField: self.dateInsert)
self.dateInsert.delegate = self.dateMaker
self.dateMaker.takeProperDateInput()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The error i get is unrecognized selector sent to instance
Create a textfield class with the default properties and implement in the view controller not a nsobject to send a textfield as parameter:
class baseTextfield: UITextField, UITextFieldDelegate {
}
class ViewController: UIViewController{
#IBOutlet weak var dateInsert: UIBaseTextField!
}
The properties are of the textfield, not of the view.

Resources