[Swift 1] Day 4 - Code Exercise Solution


#1

What do you think of variables? How’s the tip calculator?

Please share your code or answers with your classmates for the Day 4 Code Exercise and related Notebook Activity questions.

Share your code


#2

Here we are :slight_smile: Took about 30min with butchering some of my previous code :slight_smile: I think I wasted most of my time fixing errors due to me recklessly renaming labels and things post using them :smiley:
However, I tried using double value and I couldn’t, I can’t convert it to string. Also I tried making the calculation into a func and then putting in a loop, so you wouldn’t need to press a button, but it would keep recalculating when you change the value, but gave up :slight_smile:

//
//  ViewController.swift
//  TipCalculator
//
//  Created by Razvigor Andreev on 10/9/14.
//  Copyright (c) 2014 Razvigor Andreev. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var billAmountLabel: UITextField!
    
    @IBOutlet weak var tip10Label: UILabel!
    @IBOutlet weak var tip15Label: UILabel!
    @IBOutlet weak var tip18Label: UILabel!
    
    override func viewDidLoad() {
        
        
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func calculateButton(sender: AnyObject) {
    
    println("button pressed")
    
    var billAmount = (billAmountLabel.text as NSString).doubleValue
    var tip10 = (billAmount * 10 / 100)
    var tip15 = (billAmount * 15 / 100)
    var tip18 = (billAmount * 18 / 100)
    
   
        
        tip10Label.text = "\(tip10)"
        tip10Label.textColor = UIColor(red: (200/255.0), green: (97/255.0), blue: (140/255.0), alpha: 1.0)
        
        tip15Label.text = "\(tip15)"
        tip15Label.textColor = UIColor(red: (200/255.0), green: (97/255.0), blue: (5/255.0), alpha: 1.0)
        
        tip18Label.text = "\(tip18)"
        tip18Label.textColor = UIColor(red: (20/255.0), green: (97/255.0), blue: (5/255.0), alpha: 1.0)
    }
    
    

}

#3

Also I tried making the calculation into a func and then putting in a loop, so you wouldn’t need to press a button

Instead of a loop, create an action from your amount field that triggers the button on Editing Changed. Then every time the amount changes it will recalculate automatically. Something like this:

@IBAction func amountFieldChanged(sender: UITextField) {
      
        calculateTipButtonPressed(self)
    
}

#4

Add a custom tip percentage field and use Double values.
Add a UISlider to your app to control the tip percentage.
Add a text field to input multiple people to split a bill. Add output labels to display what each person owes (even split).

Code is here.
(You can run the project if you clone the repo with git clone git@github.com:Conaaando/swift_course.git)

UI:

The problem with the UISlider is that it returns floats that kind of mess up with the custom tip percentage. I have not handled this case properly. I also did not implement input validations, so it may break if users input text instead of numbers. :stuck_out_tongue:

Questions
1 What is the difference between the following two lines of code?
var x = 1 / 3
var y = 1.0 / 3.0

x is implicit Int; x = 0
y is implicit Double; y = 0.333333333333333

2 What’s a constant variable?

From Apple: If a stored value in your code is not going to change, always declare it as a constant with the let keyword. Use variables only for storing values that need to be able to change.
Constants do not change.

3 Declare a constant called PI and assign it the value 3.14159265359.

let PI = 3.14159265359

4 How much memory does an Int or a Double use?

According to this guy:

A plain Int stores the raw value in eight bytes of memory, as expected. The optional type adds an extra byte at the end to signal whether or not a value is present. If that trailing byte is zero, a value is present. If that trailing byte is 1, the optional contains nil. Thus, optional Ints take up nine bytes rather than eight.

Couldn’t find a reference to Double.


#5

Can’t do the challenge. Can’t figure how to put the slider to take the tip value on my own.


#6

Awesome job man :slight_smile:

I am just gonna put this link of what I’ve earlier posted: this kinda helped me understand the Doubles better.
Hope it helps you.


#7

Great link! Thank you!


#8

Here my code for today.
I get rid off the calculate button, because i found it more fun to have the result as we type an amount or play with the sliders.
I build the percentage slider from 1 to 50% with a 0.5% step.
I set another slider for the persons involved.
The UI :
Portrait :

Landscape :

And the code :

import UIKit

class ViewController: UIViewController {
    
    //User input
    @IBOutlet weak var amountTextField: UITextField!

    // Labels
    @IBOutlet weak var tipPercentageLabel: UILabel!
    
    @IBOutlet weak var numberOfPersonLabel: UILabel!
    @IBOutlet weak var tipAmountLabel: UILabel!
    @IBOutlet weak var totalBillLabel: UILabel!
    @IBOutlet weak var billPerPersonLabel: UILabel!
    
    //Sliders
    @IBOutlet weak var tipSlider: UISlider!
    @IBOutlet weak var personSlider: UISlider!
    
    //Variables
    var tipPercentage:Double = 0.10
    var numberOfPerson:Int = 1
    let numberFormatter:NSNumberFormatter = NSNumberFormatter()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        setupContainer()
        
        let notificationCenter = NSNotificationCenter.defaultCenter()
        notificationCenter.addObserver(
            self,
            selector: "textFieldTextChanged:",
            name:UITextFieldTextDidChangeNotification,
            object: nil
        )
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func setupContainer() {
        

        tipSlider.minimumValue = 0
        tipSlider.maximumValue = 100
        tipSlider.value = 20
        tipSlider.addTarget(self, action: "sliderTipChanged:", forControlEvents: .ValueChanged)
        
        personSlider.minimumValue = 1
        personSlider.maximumValue = 30
        personSlider.value = 1
        personSlider.addTarget(self, action: "sliderPersonChanged:", forControlEvents: .ValueChanged)
        
        amountTextField.text = ""

        refreshCalculation()

    }
    
    func textFieldTextChanged(sender : AnyObject) {
        
        refreshCalculation()
    }
    
    func refreshCalculation() {

        numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
        if let amount = numberFormatter.numberFromString(amountTextField.text) as? Double {
            
            let tipAmount = amount * tipPercentage
            let totalBill = amount + tipAmount
            let billPerPerson = totalBill / Double(numberOfPerson)
            numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
            tipAmountLabel.text = numberFormatter.stringFromNumber(tipAmount)
            totalBillLabel.text = numberFormatter.stringFromNumber(totalBill)
            billPerPersonLabel.text = numberFormatter.stringFromNumber(billPerPerson)
            
        } else {
            
            tipAmountLabel.text = "-"
            totalBillLabel.text = "-"
            billPerPersonLabel.text = "-"
        }
        
        numberFormatter.numberStyle = NSNumberFormatterStyle.PercentStyle
        numberFormatter.minimumFractionDigits = 1
        numberFormatter.maximumFractionDigits = 1
        tipPercentageLabel.text = self.numberFormatter.stringFromNumber(tipPercentage)
        
        numberOfPersonLabel.text = "\(numberOfPerson)"
        
    }
    
    func sliderTipChanged(slider:  UISlider) {
       
        tipPercentage = Double(round(slider.value)) / 200.0
        refreshCalculation()
    }
    
    func sliderPersonChanged(slider:  UISlider) {
        
        numberOfPerson = Int(round(slider.value))
        refreshCalculation()
    }
}

Last word (for those who have read so deep :slight_smile: ) as i have already done in the Day 2 exercice i didn’t use the as NSString thing to go from string to double because it doesn’t caught exception and could lead to funny errors like :

The use of the formater made possible to caught exceptions and set the result to “-” if the amount is not a valide value.


#9

I was able to place and connect slider, show custom tip.
Couldn’t figure out how to do total of tip + amount or how to split for a number of person.
I was able to split the tip when setting the variable in the code but wasn’t able to grab the value from the textfield… float not mixing with int not mixing with double etc etc etc. Seems so simple to calculate this… but couldn’t figure out the right syntax. Looking at examples from others I still don’t understand those ‘return’ or ‘refresh’.

//
// ViewController.swift
// TipCalculator
//
// Created by Eloise Camire on 2014-10-10.
// Copyright © 2014 Eloise Camire. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var amountTextField: UITextField!
@IBOutlet weak var tip10Label: UILabel!
@IBOutlet weak var tip15Label: UILabel!
@IBOutlet weak var tip20Label: UILabel!
@IBOutlet weak var customTipLabel: UILabel!
@IBOutlet weak var slider: UISlider!
@IBOutlet weak var customTipDollar: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    calculateTipButtonPressed(self)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
@IBAction func calculateTipButtonPressed(sender: AnyObject) {
    println("tip")

    var amount = (amountTextField.text as NSString).doubleValue
    
    var tip10 = amount * 0.10
    var tip15 = amount * 0.15
    var tip20 = amount * 0.20
    
    
    //format numbers for currency
    
    let numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    
    tip10Label.text = numberFormatter.stringFromNumber(tip10)
    tip15Label.text = numberFormatter.stringFromNumber(tip15)
    tip20Label.text = numberFormatter.stringFromNumber(tip20)
    
}




@IBAction func sliderValueChanged(sender: UISlider) {
    var amount2 = (amountTextField.text as NSString).doubleValue
    var sliderValue = Int(sender.value)
    var myTipPct = Double (sliderValue) / 100.0
    
    let pctFormatter = NSNumberFormatter()
    pctFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    
    var myTipDollar = amount2 * myTipPct

    customTipLabel.text = "\(Int(sliderValue)) %"
    customTipDollar.text = pctFormatter.stringFromNumber(myTipDollar)
    
}

}


#10

Awesome job @Paradisiak !

Love the changes, and great tip on not using the NSString method.

1o3 will get interpreted as 1 from what I remember, which makes sense with your output. The first number get’s parsed, everything else is ignored from the NSString method.

NSNumberFormatter get’s the job done, good find! Also nice use of the optional value to test it’s conversion. We’ll talk about that more on Monday.


#11

Swift unlike other programming languages requires that you explicitly set the types.

We discussed types a little bit yesterday. Basically Swift won’t allow you to add a Movie to a Picture, unless you make the operation explicit.

It’s to prevent errors, but it can be confusing for beginners. Do something like the following line

var result = Double(amount) +  Double(tip10)

#12

ok thanks. I could manage to do it with Double( )
main problem is the Total by Person only update once you change the slider value! :slight_smile: but I will leave it as is for now.

class ViewController: UIViewController {

@IBOutlet weak var amountTextField: UITextField!
@IBOutlet weak var tip10Label: UILabel!
@IBOutlet weak var tip15Label: UILabel!
@IBOutlet weak var tip20Label: UILabel!
@IBOutlet weak var customTipLabel: UILabel!
@IBOutlet weak var slider: UISlider!
@IBOutlet weak var customTipDollar: UILabel!
@IBOutlet weak var total: UILabel!
@IBOutlet weak var nbOfPeople: UITextField!
@IBOutlet weak var totalByPerson: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    calculateTipButtonPressed(self)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
@IBAction func calculateTipButtonPressed(sender: AnyObject) {
    println("tip")

    var amount = (amountTextField.text as NSString).doubleValue
    
    var tip10 = amount * 0.10
    var tip15 = amount * 0.15
    var tip20 = amount * 0.20
    
    
    //format numbers for currency
    
    let numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    
    tip10Label.text = numberFormatter.stringFromNumber(tip10)
    tip15Label.text = numberFormatter.stringFromNumber(tip15)
    tip20Label.text = numberFormatter.stringFromNumber(tip20)
    
}




@IBAction func sliderValueChanged(sender: UISlider) {
    var amount2 = (amountTextField.text as NSString).doubleValue
    var sliderValue = Int(sender.value)
    var myTipPct = Double (sliderValue) / 100.0
    
    let pctFormatter = NSNumberFormatter()
    pctFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    
    var myTipDollar = amount2 * myTipPct

    customTipLabel.text = "\(Int(sliderValue)) %"
    customTipDollar.text = pctFormatter.stringFromNumber(myTipDollar)
    
    var result = Double(amount2) + Double(myTipDollar)
    total.text = pctFormatter.stringFromNumber(result)
    
    var group = (nbOfPeople.text as NSString).doubleValue
    var splitResult = Double(result) / Double(group)
    totalByPerson.text = pctFormatter.stringFromNumber(splitResult)
    
}

}


#13


Questions

  1. x Int, y Double
  2. “If a stored value in your code is not going to change, always declare it as a constant with the let keyword. Use variables only for storing values that need to be able to change”(From Apple web site) Constants never change.
  3. let PI = 3.14159265359
  4. I could not find reference, may I not enter the right words (my bad English probably)

#14

@joseluisbr Awesome! Great use of the stepper for the number of people, I didn’t even think of it.

The layout is great, I’d just use “Tip %” instead of “% Tip”

You could also right-align the amount, and format it to show the $… it’ll take a little extra effort to get that working.

-Paul


#15

@anderssongreene Did you look at any code tutorials?

Did you read any of the code examples from other students?

I will say it will be challenging, but there are many videos on it, so you might find another tutorial that could help point you in the right direction.


#16

1. What is the difference between the following two lines of code?

var x = 1 / 3
var y = 1.0 / 3.0

Solution: x is Int and y is Double

2. What’s a constant variable?
A constant variable is determined by the let reserved word, constant means, we can’t change the literal once it is stated.

3. Declare a constant called PI and assign it the value 3.14159265359.

let PI: Double = 3.14159265359 or let PI = 3.14159265359

4. How much memory does an Int or a Double use?
Int = 32-bit on 32-bit platform & 64-bit on 64-bit platform
Double = 64-bit floating-point number

Code samble: https://gist.github.com/fddd965a02fe765c9026.git


#18

Ok, that took quite a while with these sliders…I think I finally got it, thanks to the guy that did it before me, it was really helpful to look at their code. I It took me an extra hours to figure out how to make it refresh on any change, but I think it works. If anyone can look and tell me if you see something disturbing I would appreciate it :slight_smile:

Here is the file:

https://drive.google.com/file/d/0B00fLVsdls5Vd3N6QXhPRmZSR0k/view?usp=sharing

//
//  ViewController.swift
//  TipCalclator2
//
//  Created by Razvigor Andreev on 10/12/14.
//  Copyright (c) 2014 Razvigor Andreev. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    
    
    // Labels
    
    @IBOutlet weak var billAmountLabel: UILabel!
    
    
    @IBOutlet weak var tipLabel: UILabel!
    
    @IBOutlet weak var totalPlusTipLabel: UILabel!
    
    @IBOutlet weak var tipPerPersonLabel: UILabel!

    @IBOutlet weak var totalPerPersonLabel: UILabel!
    
    // Outputs
    
    @IBOutlet weak var tipPercentageLabel: UILabel!
    
    @IBOutlet weak var personsLabel: UILabel!
    @IBOutlet weak var tipOutlet: UITextField!
    @IBOutlet weak var total: UITextField!
    @IBOutlet weak var tipPerPerson: UITextField!
    @IBOutlet weak var totalPerPerson: UITextField!
    
    
    
    // Input
    
    @IBOutlet weak var billAmountField: UITextField!
    
    // variables
    
    var amountDouble = Double(50)
    var sliderValue = 18
    var tipPerc = 0.18
    var tip = Double(9)
    var myTip = Double(9)
    var persons = Int(1)
    
    
    // Sliders
    
    @IBOutlet weak var tipSlider: UISlider!
    @IBOutlet weak var personsSlider: UISlider!
    
    
        override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    @IBAction func tipSliderChanged(sender: UISlider) {
        
        println("tip adjusted")
        sliderValue = Int(sender.value)
        tipPerc = Double(sliderValue) * 0.01
        
        
    refresh()
    
    
    }
    
    @IBAction func personsSlider(sender: UISlider) {
        
        println("person adjusted")
        
        persons = Int(sender.value)
        personsLabel.text = "\(persons)"
    refresh()
        
    }
    
    func refresh () {
    
        println("refresh requested")
        
        let pctFormatter = NSNumberFormatter()
        pctFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
        
        amountDouble = (billAmountField.text as NSString).doubleValue
        
        tip = amountDouble * tipPerc
        
        tipPercentageLabel.text = "\(Int(sliderValue)) %"
        tipOutlet.text = pctFormatter.stringFromNumber(tip)
        var result = Double(amountDouble)+Double(tip)
        total.text = pctFormatter.stringFromNumber(result)
        
        var personsDouble = Double(persons)
        tipPerPerson.text = pctFormatter.stringFromNumber(tip/personsDouble)
        myTip = Double(tip/personsDouble)
        totalPerPerson.text = pctFormatter.stringFromNumber(result / personsDouble)
        
        
    
    }
    
        
        
    @IBAction func billAmountChanged(sender: AnyObject) {
        
        println("amount changed")
        refresh()
    }
        
        
    
    
    
   
}

#19

Thanks Paul I’ll try.
I’m using Decimal keyboard and got this error

“TipCalculator[7877:1450942] Can’t find keyplane that supports type 8 for keyboard iPhone-PortraitChoco-DecimalPad; using 257390182_PortraitChoco_iPhone-Simple-Pad_Default”

Do I need add or declare something?

Jose Luis


#20

This exercise was very challenging for me because I was looking at everyone’s examples and I got caught up trying to make something and failed many, many times. I finally gave up and decided to get a working solution down so that I can catch back up with the class. I plan on revisiting this exercise know that I figured it out (I think) and would love to add the step and slider option to the app. I kept encountering issues like: if I simply wanted to change the percentage numbers from say 10% to 18% I would change the code and get red stop signs everywhere. If I changed it back to how it was it worked again. I did change the instances everywhere to that the Labels and vars were correct and matched but I need to move on. Any thoughts on why this is happening would be helpful.

The payoff was when I figured it all out and got this working. I was so happy.

Here is my layout that will get some lovin’ at a later date:


Here is my code:

//
// ViewController.swift
// Tip Calculator 1b
//
// Created by Timothy Morse on 10/19/14.
// Copyright © 2014 Timothy Morse. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var billTotalField: UITextField!
@IBOutlet weak var tip10Label: UILabel!
@IBOutlet weak var tip15Label: UILabel!
@IBOutlet weak var tip20Label: UILabel!
@IBOutlet weak var bill10Label: UILabel!
@IBOutlet weak var bill15Label: UILabel!
@IBOutlet weak var bill20Label: UILabel!


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    
    calculateTipButtonPressed(self)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.

}

@IBAction func calculateTipButtonPressed(sender: AnyObject) {

    println("Tip")
    
var amount = (billTotalField.text as NSString).doubleValue

var tip10 = amount * 0.10
var tip15 = amount * 0.15
var tip20 = amount * 0.20
var bill10 = amount * 0.10 + amount
var bill15 = amount * 0.15 + amount
var bill20 = amount * 0.20 + amount

// tip10Label.text = “$(tip10)”
// tip15Label.text = “$(tip15)”
// tip20Label.text = “$(tip20)”

// Format Numbers for Currency
    
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle

tip10Label.text = numberFormatter.stringFromNumber(tip10)
tip15Label.text = numberFormatter.stringFromNumber(tip15)
tip20Label.text = numberFormatter.stringFromNumber(tip20)
    
bill10Label.text = numberFormatter.stringFromNumber(bill10)
bill15Label.text = numberFormatter.stringFromNumber(bill15)
bill20Label.text = numberFormatter.stringFromNumber(bill20)

    
}

}


My Answers to the Questions:

  1. What is the difference between the following two lines of code?
    x is an Integer (0)
    y is a Double (0.33)

  2. What’s a constant variable?
    A variable whose value cannot be changed once it has been assigned a value.

  3. Declare a constant called PI and assign it the value 3.14159265359.
    let PI = 3.14159265359

  4. How much memory does an Int or a Double use?
    int: 4 bytes
    double: 8 bytes

1 bytes = 8 bits

Source: https://answers.yahoo.com/question/index?qid=20090408065010AAX0hM3

Thank you to those that posted your solutions.


#21

Great work!

It can be hard to get things right the first time. A bit of persistence is really important to success.

I’m working to include more sample code for the Code Exercises in future lessons, as well as the first 14 lessons.