Working on a calculator in swift and I'm stuck - ios

I'm new to coding and just learning now. swift code and I'm running into a snag and can't seem to figure it out, so I've been flowing along with the Stanford YouTube channel on swift coding and they are doing a calculator. Currently we are trying to get double value.
#IBOutlet weak var display: UILabel!
var userIsInTheMiddleOfTypingANumber = false
#IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTypingANumber {
display.text = display.text! + digit
} else {
display.text = digit
userIsInTheMiddleOfTypingANumber = true
}
}
var operandStack: Array<Double> = Array<Double>()
#IBAction func enter() {
userIsInTheMiddleOfTypingANumber = false
operandStack.append(displayValue)
print("operandStack = \(operandStack)")
}
var displayValue: Double {
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
// This is my problem and comes back with exc_bad_instruction (code=exc_i387_invop any help would be greatly appreciated on this! thank you for your time!
}
set {
display.text = "\(newValue)"
userIsInTheMiddleOfTypingANumber = false
}
}

In addition to Martin R: Actually you have two big problems and both are related to your unwrapping of optionals.
First is this line:
#IBOutlet weak var display: UILabel!
The problem is the !. An #IBOutlet links to a view in a storyboard. But depending on the stage the GUI is at it may be that this displaywon`t exist yet. So this should be a optional marked with ? not !. Then your compiler would complain about this line:
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
He would complain that display probably does not exist and that you can`t just do that. You would probably "solve" the problem like this:
return NSNumberFormatter().numberFromString(display!.text!)!.doubleValue
But this will either fail if displayist not ready or of the NSNumberFormatter can`t convert the string to a number. And you will never know why. So stop using forced unwrapping. You have different tools to solve your problem though. But at first you should think about your problem. Your problem is in the end that not every string can be converted to a double. So you have to deal with this at some point. There are countless possibilities to do so. But as a starter, if you have code that will crash if an optional (can be nil value) is actually nil then you can use this pattern:
if let thisValueIsNotNil = dontKnowIfItIsNil {
// Do something with thisValueIsNotNil - it is save
}
Edit: The core problem an mechanism are pretty well explained IMO in this blog post:
http://appventure.me/2014/06/13/swift-optionals-made-simple/

Related

Passing Int property from textfield back to controller

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.
}

Unwrapping issue in swift

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]()

Limiting User to One Decimal Point UILabel Swift2

So, if you read the question then you know the problem. I have read over a load of other articles about one decimal but all of them use this textfield thingy. I'm using a UILabel and have no idea how to only make one decimal point appear. Here is some of my code.
#IBOutlet weak var Screen: UILabel!
var firstNumber = Float()
var secondNumber = Float()
var result = Float()
var operation = ""
var isTypingNumber = false
var dotString = "."
#IBAction func Dot(sender: AnyObject) {
let dot = sender.currentTitle
Screen.text = Screen.text! + dot!!
}
I think I have provided enough code to fix the problem. The problem is I can enter 8.22.197.161... or as many decimals as the label can fit. I want it to stop putting more decimals after validating that there is only 1. I'm a pretty beginner noob at this stuff so any help will be appreciated as I have been breaking my head over this for the last couple days.
So, if there is no dot in the string, then you want to append a dot. Swift has something called an “if statement” that helps a lot:
if let text = Screen.text {
if !text.containsString(".") {
Screen.text = text + "."
}
}

Questions regarding to value setting and getters and setters in Swift

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.

Why does this swift code work when newValue has nothing assigned to it?

import UIKit
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var inMid = false
#IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if inMid{
display.text = display.text! + digit
}else{
display.text = digit
inMid = true
}
}
var operandStack = Array<Double>()
#IBAction func enter() {
inMid = false
operandStack.append(displayValue)
println("operandStack = \(operandStack)")
}
var displayValue:Double{
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set{
display.text = "\(newValue)"
}
}
}
This is the part of code used in the latest Standford IOS 8 course using swift to build a calculator(Youtube address: https://www.youtube.com/watch?v=QLJtT7eSykg)
Every time I call enter() (press enter), a new number is supposed to be saved in a stack. For example: "8, enter()" --> {8}, "16, enter()" --> {8,16}.
I got confused about the computed property "displayValue" here. There is nothing assigned to the "newValue". If there is something like "displayValue = 8", then I know "newValue" is 8, and it all makes sense. But there is not such thing.
How come it still works?
(What I mean is not the name "newValue" itself,I know it is a default setting by Swift, instead, the missing of assigned value is the one that confuses me)
"newValue" is an implicitly defined variable in swift.
What he does is a very neat way of letting the label show the values of the double "displayValue" Every time displayValue is changed, the label is automatically updated with the newest (double) value.
Or when you write: displayValue = 45.0, the label will also show this value. Very handy when you constantly need to update textfield or labels with data you get from databases, rest interfaces, etc. What "newValue" does is taking the last "setter" value holding that.

Resources