[Swift 1] Day 4 - Code Exercise Solution


#22

Hi Folks,
I seem to be the one always finding issues :frowning:

Can anyone help me…
Im trying to add a slider and I’ve tried numerous ways of doing it. Struggled quite a bit and then I tried to use the below code. However Im getting a fatal error on this
customPercentageLabel.text = "(Int(sliderCustomTipValue)) %"
with the message “Fatal error: unexpectedly found nil while unwrapping an Optional value”.

I think its to do with the double value and google isn’t really helping me. Any Ideas?

Thanks

//
// ViewController.swift
// TipCalculator
//
// Created by Nicholas Allibone on 23/11/2014.
// Copyright © 2014 Nicholas Allibone. 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 tipSlider: UISlider!
@IBOutlet weak var customPercentageLabel: UILabel!
@IBOutlet weak var customTip: 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 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

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

    // Format Numbers for Currency!
    let numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    //numberFormatter.locale = NSLocale.currentLocale().localeIdentifier
    //numberFormatter.locale = NSLocale(localeIdentifier: "en_UK")
    
    tip10Label.text = numberFormatter.stringFromNumber(tip10)
    tip15Label.text = numberFormatter.stringFromNumber(tip15)
    tip20Label.text = numberFormatter.stringFromNumber(tip20)
    
    println("Current locale: \(NSLocale.currentLocale().localeIdentifier)")

    
}


@IBAction func customTipSlider(sender: UISlider) {
    var customAmount = (amountTextField.text as NSString).doubleValue
    var sliderCustomTipValue = Int(sender.value)
    var tipPercentage = Double (sliderCustomTipValue) / 100.0
    
    let percentageFormatter = NSNumberFormatter()
    percentageFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    
    var customerTip = customAmount * tipPercentage
    
    customPercentageLabel.text = "\(Int(sliderCustomTipValue)) %"
    customTip.text = percentageFormatter.stringFromNumber(customerTip)

}

}


#23

@NickAllibone

I believe that you have a missing connection from the User interface (storyboard) to the code.

customPercentageLabel is not connected, which means it’s nil, which is the meaning behind your error message.

Double check your connections by right clicking on the customPercentageLabel. If there isn’t a connection, reconnect it to the same property. You may have renamed something, which can cause this type of issue.


#24

Best thing to do is upload all your code on GitHub, so we can see it with the interface.
One thing that comes to mind is that when you define variables for the slider you might have to give them starting values.
So if you are using a variable somewhere, but you have just declared it without assigning it a value, then you will get an error while trying to use it as it will be ‘nil’


#25

@PaulSolt
Thanks Paul you where right. Newbie error lol. Got it all working now. The only down side is Im still struggling with the localisation setting and the auto alignments. I’ll go over the tutorial again on the alignments first before asking for help.

One quick question. Could you tell me where the localisation setting is in Xcode. Cant seem to find or on google. My mac settings are correct and set up for the UK, but still getting US.

Thanks :smiley:


#26

@ravenshore. Thanks for the advice, got the majority of the main issues fixed. Just the layout to play with and localisation.

I’ll setup a gitHub account so any issues in the future I can upload the code to.

Cheers


#27

I think it’s taking the setting that you can access within the IOS Simulator under Settings ? Like on an actual iPhone…


#28

@ravenshore and @NickAllibone Try this setting in Xcode for the app’s Scheme.

When I set this and then run the code in viewDidLoad, it works as expected for the region. Here is the United Kingdom’s results.

let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
numberFormatter.locale = NSLocale.currentLocale()

println("locale: \(numberFormatter.locale?.localeIdentifier)")

var cost = 3.49
var costString = numberFormatter.stringFromNumber(cost)

println("cost formatted: \(costString)")

numberFormatter.locale = NSLocale(localeIdentifier: "en_UK")

costString = numberFormatter.stringFromNumber(cost)
println("cost formatted: \(costString)")

Output

locale: Optional("en_GB")
cost formatted: Optional("£3.49")
cost formatted: Optional("£3.49")

#29

Hi I am stuck on this, I have a slider that has the number of people to split the bill by but the method for calculating the totals cannot access the variable splitValue. Can anyone help please?

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var amountTextField: UITextField!

@IBOutlet weak var tipTenLabel: UILabel!
@IBOutlet weak var tipFifteenLabel: UILabel!
@IBOutlet weak var tipTwentyLabel: UILabel!

@IBOutlet weak var twentyTotalLabel: UILabel!
@IBOutlet weak var fifteenTotalLabel: UILabel!
@IBOutlet weak var tenTotalLabel: UILabel!
@IBOutlet weak var splitLabel: UILabel!

@IBOutlet weak var perPersonTenLabel: UILabel!
@IBOutlet weak var perPersonFifteenLabel: UILabel!
@IBOutlet weak var perPersonTwentyLabel: UILabel!



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

    var splitValue = 2.0
    
    caclulateTipButtonPressed(self)
}

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


@IBAction func splitNumberSlider(sender: UISlider) {
    
    var splitValue = Int(sender.value)
    
    splitLabel.text = "\(splitValue)"
    
    
}

@IBAction func caclulateTipButtonPressed(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

    tipTenLabel.text = tip10.description
    tipFifteenLabel.text = tip15.description
    tipTwentyLabel.text = "$\(tip20)"

// Total Price to pay

    var total10 = amount + tip10
    var total15 = amount + tip15
    var total20 = amount + tip20
    
    tenTotalLabel.text = total10.description
    fifteenTotalLabel.text = total15.description
    twentyTotalLabel.text = total20.description

// Price per person

    var split10 = total10 / splitValue
    var split15 = total15 / splitValue
    var split20 = total20 / splitValue
    
    perPersonTenLabel.text = split10.description
    perPersonFifteenLabel.text = split15.description
    perPersonTwentyLabel.text = split20.description

// format number for currency

    let numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    numberFormatter.locale = NSLocale(localeIdentifier: "en_UK")
    
    tipTenLabel.text = numberFormatter.stringFromNumber(tip10)
    tipFifteenLabel.text = numberFormatter.stringFromNumber(tip15)
    tipTwentyLabel.text = numberFormatter.stringFromNumber(tip20)

    tenTotalLabel.text = numberFormatter.stringFromNumber(total10)
    fifteenTotalLabel.text = numberFormatter.stringFromNumber(total15)
    twentyTotalLabel.text = numberFormatter.stringFromNumber(total20)
    
    perPersonTenLabel.text = numberFormatter.stringFromNumber(split10)
    perPersonFifteenLabel.text = numberFormatter.stringFromNumber(split15)
    perPersonTwentyLabel.text = numberFormatter.stringFromNumber(split20)
    
    
}

}


#30

Hi here is my one, I wanted to do a slider version but couldnt get the output from the slider to be used in calculation for the split in the other method. So I made a simpler version to move to the next tutorial.

import UIKit

class ViewController: UIViewController {

// linkage

@IBOutlet weak var amountTextField: UITextField!
@IBOutlet weak var splitTextField: UITextField!


@IBOutlet weak var tipTenLabel: UILabel!
@IBOutlet weak var tipFifteenLabel: UILabel!
@IBOutlet weak var tipTwentyLabel: UILabel!

@IBOutlet weak var twentyTotalLabel: UILabel!
@IBOutlet weak var fifteenTotalLabel: UILabel!
@IBOutlet weak var tenTotalLabel: UILabel!
@IBOutlet weak var splitLabel: UILabel!

@IBOutlet weak var perPersonTenLabel: UILabel!
@IBOutlet weak var perPersonFifteenLabel: UILabel!
@IBOutlet weak var perPersonTwentyLabel: UILabel!

// variables
var splitValue = Int(2)
var amount = Double(0.0)
var tip10 = Double(0.0)
var tip15 = Double(0.0)
var tip20 = Double(0.0)
var total10 = Double(0.0)
var total15 = Double(0.0)
var total20 = Double(0.0)
var split10 = Double(0.0)
var split15 = Double(0.0)
var split20 = Double(0.0)

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

    caclulateTipButtonPressed(self)
    
    refresh()

}

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

//
// var splitValue = Int(sender.value)
//
// splitLabel.text = “(splitValue)”
//
// refresh()

@IBAction func caclulateTipButtonPressed(sender: AnyObject) {
   
println("Tip")
    

    refresh()
    
    
}

func refresh () {

    var amount = (amountTextField.text as NSString).doubleValue
    var splitValue = (splitTextField.text as NSString).doubleValue

    

    var tip10 = amount * 0.10
    var tip15 = amount * 0.15
    var tip20 = amount * 0.20

    tipTenLabel.text = tip10.description
    tipFifteenLabel.text = tip15.description
    tipTwentyLabel.text = "$\(tip20)"

// Total Price to pay

    var total10 = amount + tip10
    var total15 = amount + tip15
    var total20 = amount + tip20
    
    tenTotalLabel.text = total10.description
    fifteenTotalLabel.text = total15.description
    twentyTotalLabel.text = total20.description

// Price per person

    var split10 = total10 / Double(splitValue)
    var split15 = total15 / Double(splitValue)
    var split20 = total20 / Double(splitValue)
    
    perPersonTenLabel.text = split10.description
    perPersonFifteenLabel.text = split15.description
    perPersonTwentyLabel.text = split20.description
    
    println("split10")

// format number for currency

    let numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    numberFormatter.locale = NSLocale(localeIdentifier: "en_UK")
    
    tipTenLabel.text = numberFormatter.stringFromNumber(tip10)
    tipFifteenLabel.text = numberFormatter.stringFromNumber(tip15)
    tipTwentyLabel.text = numberFormatter.stringFromNumber(tip20)

    tenTotalLabel.text = numberFormatter.stringFromNumber(total10)
    fifteenTotalLabel.text = numberFormatter.stringFromNumber(total15)
    twentyTotalLabel.text = numberFormatter.stringFromNumber(total20)
    
    perPersonTenLabel.text = numberFormatter.stringFromNumber(split10)
    perPersonFifteenLabel.text = numberFormatter.stringFromNumber(split15)
    perPersonTwentyLabel.text = numberFormatter.stringFromNumber(split20)
    
    
}

}


#31

You cannot access it, because you are assigning the property to a local variable.
You declare the variable inside your @IBAction func:

@IBAction func splitNumberSlider(sender: UISlider) {

    var splitValue = Int(sender.value)

    splitLabel.text = "\(splitValue)"


}

but instead you should just be resuing the var you have declared earlier.
Just take the var out from the IBAction func and it should work.
Change it to this:

@IBAction func splitNumberSlider(sender: UISlider) {

    splitValue = Int(sender.value)

    splitLabel.text = "\(splitValue)"


}

#32

Make sure you declare it as an instance variable.

var spliteValue: Float = 0.0 // declare and initialize an instance variable (property)

// Instance variables let you access a variable across methods within a code file

@IBAction func splitNumberSlider(sender: UISlider) {

    splitValue = sender.value  // use floats to get decimal places

    splitLabel.text = "\(splitValue)"
}

Up to this point in the course, I haven’t really covered instance variables and am expecting you to discover the need for using them to share data between methods (i.e.: chunks of code).


#33

Thank you am loving the course.


#34

Thank you Will try that.


#35

//

// ViewController.swift
// TipCalculator
//
// Created by taha yassine hammi on 5/9/15.
// Copyright © 2015 Tyham. 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 tipCustomLabel: UILabel!
@IBOutlet weak var tipCustomPercentageLabel: UILabel!
@IBOutlet weak var secondeTipCustomPercentageLabel: UILabel!
@IBOutlet weak var tipSlider: UISlider!

@IBOutlet weak var numberOfPersonTextField: UITextField!
@IBOutlet weak var totalLabel: UILabel!
@IBOutlet weak var tipPersonLabel: UILabel!
@IBOutlet weak var totalPersonLabel: UILabel!


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

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


@IBAction func buttonPressed(sender: AnyObject) {

    var amount = (amountTextField.text as NSString).doubleValue
    
    var tip10 = amount * 0.10
    var tip15 = amount * 0.15
    var tip20 = amount * 0.20

// tip10Label.text = tip10.description
// tip15Label.text = tip15.description
// you can use ( “(tip20)” or tip20.description ) it’s do the same job and display the value of tip20
// tip20Label.text = “(tip20)”

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

// amountTextField.text = numberFormater.stringFromNumber(amount)

    tip10Label.text = numberFormater.stringFromNumber(tip10)
    tip15Label.text = numberFormater.stringFromNumber(tip15)
    tip20Label.text = numberFormater.stringFromNumber(tip20)
    
}


@IBAction func sliderValueChanged(sender: UISlider) {
    
    let numberFormater = NSNumberFormatter()
    numberFormater.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    
    var currentValue = Int(sender.value)
    
    tipCustomPercentageLabel.text = "Custom Tip Percentage :   \(currentValue)%"
    secondeTipCustomPercentageLabel.text = "\(currentValue)%"
    
    var amount = (amountTextField.text as NSString).doubleValue
    var tipCustom = amount * (Double(currentValue) / 100)
    
    tipCustomLabel.text = numberFormater.stringFromNumber(tipCustom)
    
    var numberOfPerson = numberOfPersonTextField.text.toInt()
    var total = tipCustom + amount
    var tipPerson = tipCustom / Double(numberOfPerson!)
    var totalPerson = total / Double(numberOfPerson!)
    
    totalLabel.text = numberFormater.stringFromNumber(total)
    tipPersonLabel.text = numberFormater.stringFromNumber(tipPerson)
    totalPersonLabel.text = numberFormater.stringFromNumber(totalPerson)
    
}

}

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

var x = 1 / 3 // x of type Int ( integer)

var y = 1.0 / 3.0 // y of type Float or Double

  1. What’s a constant variable?

A variable that we cannot change it value

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

let pi = 3.14159265359

  1. How much memory does an Int or a Double use?

integer use 4 bytes (32 bits)

double use 8 bytes (64 bits)


#36

I left the first part in and added my own parts to the interface so it is cluttered. I should do a clean version. It won’t let me add a picture to the post.


#37

My calculations and code appears to be working ok, it’s the constraints that are choking my app and frustrating the life out of me… I have cleared all constraints 3 times so far and started again… But sill i have the same problem. The Calculate button and some custom fields disappearing but on wide angle using command arrow i see the buttons but chops other things off… I am wondering if i have conflicts or perhaps run out of space?


#38

If you are having really hard time with constraints, I would suggest you writing them down on paper and then manually setting them up, rather than using the ‘add missing constraints’. It’s simpler than it sounds :wink:
If you keep having problems , upload your whole project somewhere, so someone can download it and see what you are doing wrong.


#39

@felineuk Any luck with the constraints?

Can you upload your project, or email me a copy at PaulSolt@iPhoneDev.tv so I can take a look at your issue.

Did you re-watch the video on setting up layout or troubleshooting?


#40

Yes i am back from vacation with a clearer head. I will re-watch all related videos incl the troubleshooting (which i watched 4 times pre vacation) and re do the constraints and if i still have issues i will send through an email. Thanks Paul.


#41

One email winging it’s way to you Paul. I appreciate the help.