Swift - Creating UIButton when in landscape - ios

I am making a calculator app in iOS 9, Swift and with Xcode 7 and I would like to know how to create UIButtons when the user switches to landscape mode only. Adding more operators to the left of the number and AC Button and changing the constraints, shifting the buttons over to make room for the new ones. The basic calculator for iOS does this and I'm wondering how??
I'm new to iOS development and I have been web browsing to only find an overriding function called: viewWillTransitionToSize(). Is this the right function to do this sort of thing?
Also, everytime I enter the landscape view, another button gets created. How can I stop this from happening?
Attached is my programmatic creation of the UIbutton and the function I listed above.
Sorry for the array of questions/problems. I am having difficulties finding tutorials or help on this issue. Any guidance or solution will be helpful. Thank you so much.
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var outputDisplay: UILabel!
#IBOutlet weak var number7: UIButton!
#IBOutlet weak var number1: UIButton!
#IBOutlet weak var number2: UIButton!
#IBOutlet weak var number3: UIButton!
#IBOutlet weak var number4: UIButton!
#IBOutlet weak var number5: UIButton!
#IBOutlet weak var number6: UIButton!
#IBOutlet weak var number9: UIButton!
#IBOutlet weak var number8: UIButton!
#IBOutlet weak var numberZero: UIButton!
#IBOutlet weak var decimalPoint: UIButton!
#IBOutlet weak var plusMinusToggle: UIButton!
#IBOutlet weak var acClear: UIButton!
#IBOutlet weak var equalButton: UIButton!
#IBOutlet weak var multiply: UIButton!
#IBOutlet weak var divide: UIButton!
#IBOutlet weak var subtraction: UIButton!
#IBOutlet weak var addition: UIButton!
#IBOutlet weak var deletion: UIButton!
#IBOutlet weak var squareRoot: UIButton!
var typing:Bool = false
var firstNumber: Float = 0.0
var secondNumber: Float = 0.0
var operation:String = ""
var result: Float = 0.0
var valueToPass: Float = 0.0
override func viewDidLoad() {
super.viewDidLoad()
number1.layer.cornerRadius = number1.bounds.size.width / 8.0
number2.layer.cornerRadius = number2.bounds.size.width / 8.0
number3.layer.cornerRadius = number3.bounds.size.width / 8.0
number4.layer.cornerRadius = number4.bounds.size.width / 8.0
number5.layer.cornerRadius = number5.bounds.size.width / 8.0
number6.layer.cornerRadius = number6.bounds.size.width / 8.0
number7.layer.cornerRadius = number7.bounds.size.width / 8.0
number8.layer.cornerRadius = number8.bounds.size.width / 8.0
number9.layer.cornerRadius = number9.bounds.size.width / 8.0
numberZero.layer.cornerRadius = numberZero.bounds.size.width / 8.0
equalButton.layer.cornerRadius = equalButton.bounds.size.width / 8.0
deletion.layer.cornerRadius = deletion.bounds.size.width / 8.0
plusMinusToggle.layer.cornerRadius = plusMinusToggle.bounds.size.width / 8.0
decimalPoint.layer.cornerRadius = decimalPoint.bounds.size.width / 8.0
acClear.layer.cornerRadius = acClear.bounds.size.width / 8.0
addition.layer.cornerRadius = addition.bounds.size.width / 8.0
divide.layer.cornerRadius = divide.bounds.size.width / 8.0
multiply.layer.cornerRadius = multiply.bounds.size.width / 8.0
subtraction.layer.cornerRadius = subtraction.bounds.size.width / 8.0
squareRoot.layer.cornerRadius = squareRoot.bounds.size.width / 8.0
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
if (UIDevice.currentDevice().orientation.isLandscape) {
print("Device in Lanscape")
let newButton1 = UIButton(type: UIButtonType.System) as UIButton
newButton1.frame = CGRectMake(100, 100, 100, 50)
newButton1.backgroundColor = UIColor.whiteColor()
newButton1.center = CGPoint(x: number1.frame.width, y: number1.frame.height)
newButton1.layer.cornerRadius = newButton1.bounds.size.width / 8.0
self.view.addSubview(newButton1)
}
else{}
}
#IBAction func numberPressed(sender: AnyObject) {
// set the variable "number" to whichever number the user presses
let number = sender.currentTitle!
if typing {
outputDisplay.text = outputDisplay.text! + String(number!)
} else {
outputDisplay.text = number!
}
typing = true
}
#IBAction func calculationPressed(sender: AnyObject) {
typing = false
firstNumber = Float(outputDisplay.text!)!
operation = sender.currentTitle!!
}
#IBAction func equalPressed(sender: AnyObject) {
secondNumber = Float(outputDisplay.text!)!
typing = false
//arithmetic operations
if operation == "+" {
result = firstNumber + secondNumber
}
else if operation == "-" {
result = firstNumber - secondNumber
}
else if operation == "✕" {
result = firstNumber * secondNumber
}
else if operation == "÷" {
result = firstNumber / secondNumber
}
// else if operation == "%" {
// result = (firstNumber * secondNumber) / 100
// }
else if operation == "√" {
result = sqrt(firstNumber)
}
outputDisplay.text = "\(result)"
}
#IBAction func squareRoot(sender: AnyObject) {
result = sqrt(Float(outputDisplay.text!)!)
outputDisplay.text = "\(result)"
}
#IBAction func deletePressed(sender: AnyObject) {
if outputDisplay.text!.characters.count != 0 {
outputDisplay.text = outputDisplay.text!.substringToIndex(outputDisplay.text!.endIndex.predecessor())
}
else{
outputDisplay.text = "0"
}
}
#IBAction func plusMinus(sender: AnyObject) {
if( outputDisplay.text![outputDisplay.text!.startIndex] == "-"){
outputDisplay.text!.removeAtIndex(outputDisplay.text!.startIndex)
}else{
outputDisplay.text!.insert("-", atIndex: outputDisplay.text!.startIndex)
}
}
#IBAction func decimal(sender: AnyObject) {
let decimal = sender.currentTitle!
outputDisplay.text = outputDisplay.text! + decimal!
}
#IBAction func clear(sender: AnyObject) {
result = 0
firstNumber = 0
secondNumber = 0
outputDisplay.text = "0"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

I would do this using Size Classes. You can design different layouts and button arrangements in storyboard using the different size classes. If this application is on the iPhone, you would use Compact width and Regular height when in Portrait and Compact height and Regular width when in Landscape.

Related

Cannot use instance member 'userCard1' within property initializer; property initializers run before 'self' is available error [duplicate]

This question already has answers here:
How to initialize properties that depend on each other
(4 answers)
Closed 2 years ago.
Trying to make a simple Blackjack app to get comfortable with using Xcode. I've never coded in Swift before and have a little experience in C++. Having an error I don't know how to fix. I'm having trouble applying other answers to similar questions to my situation.
I'm not totally sure what's causing the problem, let alone how to fix it :)
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
var balance = 500
let suits = ["h","d","c","s"]
//user card declarations
#IBOutlet weak var userCard1: UIImageView!
#IBOutlet weak var userCard2: UIImageView!
#IBOutlet weak var userCard3: UIImageView!
#IBOutlet weak var userCard4: UIImageView!
#IBOutlet weak var userCard5: UIImageView!
#IBOutlet weak var userCard6: UIImageView!
#IBOutlet weak var userCard7: UIImageView!
#IBOutlet weak var userCard8: UIImageView!
#IBOutlet weak var userCard9: UIImageView!
#IBOutlet weak var userCard10: UIImageView!
//dealer card declarations
#IBOutlet weak var dealerCard1: UIImageView!
#IBOutlet weak var dealerCard2: UIImageView!
#IBOutlet weak var dealerCard3: UIImageView!
#IBOutlet weak var dealerCard4: UIImageView!
#IBOutlet weak var dealerCard5: UIImageView!
var win = false
var bet = 0
//bet label
#IBOutlet weak var betLabel: UILabel!
//bet slider
#IBAction func betSlider(_ sender: UISlider) {
betLabel.text = String(Int(sender.value))
}
#IBOutlet weak var betSliderValue: UISlider!
var userCardSlot = 3
var dealerCardSlot = 3
var userTotal = 0
var dealerTotal = 0
//user cards displayed
var userCardArray = [userCard1, userCard2, userCard3, userCard4, userCard5, userCard6, userCard7, userCard8, userCard9, userCard10]
//dealer cards displayed
var dealerCardArray = [dealerCard1, dealerCard2, dealerCard3, dealerCard4, dealerCard5]
//hit button
#IBAction func hitTapped(_ sender: Any) {
var cardNum = Int.random(in: 2...14)
var cardSuit = Int(arc4random()) % 4
userCardArray[userCardSlot].image = UIImage(named: "\(cardSuit)card\(cardNum)")
}
//stand button
#IBAction func standTapped(_ sender: Any) {
for userTotal in userCardArray.reversed() {
userTotal += cardNum
}
for dealerTotal in dealerCardArray {
dealerTotal += cardNum
}
while dealerTotal < 17 {
dealerCardSlot += 1
dealerCardArray[dealerCardSlot].image = UIImage(named: "\(cardSuit)card\(cardNum)")
}
if dealerTotal <= userTotal {
win = true
} else {
win = false
}
}
#IBAction func newRoundTapped(_ sender: Any) {
bet = Int(betSliderValue.value)
userCardArray[0].image = UIImage(named: "\(cardSuit)card\(cardNum)")
userCardArray[1].image = UIImage(named: "\(cardSuit)card\(cardNum)")
dealerCardArray[0].image = UIImage(named: "\(cardSuit)card\(cardNum)")
dealerCardArray[0].image = UIImage(named: "Red_back.jpg")
//prompt for hit or stand
if win == true {
balance += (bet * 2)
} else {
balance -= bet
}
}
}
Any help's appreciated!
You generally cannot use one property to initialize another outside of init, because when you do:
var b = a + 1
the compiler implicitly does:
var b = self.a + 1
but self is not yet available; it's only available during the init.
The only exception is a lazy property initializer:
lazy var b: Int = self.a + 1
In your case, you can move the initialization into init:
var userCardArray: [UIImageView]
init() {
self.userCardArray = [userCard1, userCard2, ... ]
}

Calculating and displaying as label

I want to calculate Runs per Overs and display on a Run Rate Label.
As you can see in my code, the Run Rate will change as i'm using steppers for Runs and Overs.
The run rate need to be displayed up to 2 decimal points (eg. 4.50 or 10.74 etc.)
I want to create function but I don't know how to calculate.
How can I do this?
// RUNS
var runsInt = 0
var oversFloat: Float = 0.0
var runRate: Double = 0.0
#IBOutlet weak var runsLabel: UILabel!
#IBOutlet weak var displayRunsLabel: UILabel!
#IBOutlet weak var oversLabel: UILabel!
#IBOutlet weak var oversRectangle: UILabel!
#IBOutlet weak var displayOversLabel: UILabel!
#IBOutlet weak var runRateLabel: UILabel!
#IBOutlet weak var displayRunRateLabel: UILabel!
#IBAction func RunStepper(_ sender: UIStepper) {
let runsValue = Int(sender.value)
displayRunsLabel.text = String(runsValue)
}
// OVERS
#IBAction func OversStepper(_ sender: UIStepper) {
let value = Int(sender.value)
let remainder = value % 10
if remainder == 6 {
sender.value = Double(value + 4)
} else if remainder == 9 {
sender.value = Double(value - 4)
}
displayOversLabel.text = String(format: "%.1f", sender.value / 10)
}
I used this page for information on calculating run rate.
runRate = (total runs scored)/(total overs faced)
Note: If overs is 47.5, the stepper value will be 475.0 and
oversInt will be set to 475. When calculating runRate, 47.5
actually represents 47 5/6 which we can calculate as
Double(oversInt / 10) + Double(oversInt % 10) / 6
Create a function called calculateRunRate and
add property observers (didSet) to runsInt and oversInt to trigger the calculation of runRate. Then anytime either of those values changes, runRate will be recalculated and the displayRunRate label will be updated.
// RUNS
var runsInt = 0 {
didSet {
calculateRunRate()
}
}
#IBOutlet weak var runsLabel: UILabel!
#IBOutlet weak var displayRunsLabel: UILabel!
#IBAction func RunStepper(_ sender: UIStepper) {
runsInt = Int(sender.value)
displayRunsLabel.text = String(runsInt)
}
// OVERS
var oversInt = 0 {
didSet {
calculateRunRate()
}
}
#IBOutlet weak var oversLabel: UILabel!
#IBOutlet weak var oversRectangle: UILabel!
#IBOutlet weak var displayOversLabel: UILabel!
#IBAction func OversStepper(_ sender: UIStepper) {
var value = Int(sender.value)
let remainder = value % 10
if remainder == 6 {
value += 4
} else if remainder == 9 {
value -= 4
}
sender.value = Double(value)
oversInt = value
displayOversLabel.text = String(format: "%.1f", sender.value / 10)
}
// RUN RATE
var runRate = 0.0
let maxOvers = 40.0
#IBOutlet weak var runRateLabel: UILabel!
#IBOutlet weak var displayRunRateLabel: UILabel!
#IBOutlet weak var displayRequiredRunRateLabel: UILabel!
func calculateRunRate() {
var oversDouble = 0.0
// Don't divide by zero
if oversInt == 0 {
// can this even happen?
// set runRate to some value that makes sense
runRate = 0.0
} else {
oversDouble = Double(oversInt / 10) + Double(oversInt % 10) / 6
runRate = Double(runsInt) / oversDouble
}
displayRunRateLabel.text = String(format: "%.2f", runRate)
// required run rate
let targetScore = Int(targetScoreLabel.text ?? "") ?? 0
var requiredRunRate = 0.0
if oversDouble < maxOvers {
requiredRunRate = Double(targetScore - runsInt) / (maxOvers - oversDouble)
}
displayRequiredRunRateLabel.text = String(format: "%.2f", requiredRunRate)
}

UIView textFieldShouldReturn not working

I am having some problems with function textFieldShouldReturn as far at i understand it should be called when enter are pressed on the keyboard but it does not. I have tried to search for solution on google and here but have not found a answer that solved the problem because most of the answers here on the webpage i have fund are a 3 years or older and the solutions from those did not help much.
I am using it in a UIView where the delegates for the textField is set in the function awakeFromNib() and i have tried some other delegate function textViewDidChangeSelection that does work so i am at a lost why it is not working.
Here is how the xib file looks
Here is the code that i am using as a popup:
import UIKit
class CuePointPopup: UIView,UITextFieldDelegate,UITextViewDelegate
{
#IBOutlet var labelCueNumberInImage: UILabel!
#IBOutlet var labelCueNumber: UILabel!
#IBOutlet var labelLayerName: UILabel!
#IBOutlet var labelPageNumber: UILabel!
#IBOutlet weak var view: UIImageView!
#IBOutlet var textFieldWhoText: UITextField!
#IBOutlet var textViewWhatText: UITextView!
#IBOutlet var textFieldWhereText: UITextField!
#IBOutlet var textFieldPageNumber: UITextField!
#IBOutlet var textFieldCueText: UITextField!
#IBOutlet var boxArrowLeft: UIImageView!
#IBOutlet var boxArrowRight: UIImageView!
#IBOutlet var boxArrowLeftTopConstraint: NSLayoutConstraint!
#IBOutlet var boxArrowRightTopConstraint: NSLayoutConstraint!
var cuePointObj:CuePoint!
var blockBtnClickedSave:((CuePoint) -> ())!
var blockBtnClickedCancel:((CuePoint) -> ())!
var blockBtnClickedDelete:((CuePoint) -> ())!
var blockTextChangedForPageNumber:((String, CuePoint) -> ())!
#IBOutlet var btnOutletVisibleOnPage: UIButton!
var isVisible = false
class func loadNib() -> CuePointPopup
{
return Bundle.main.loadNibNamed("CuePointPopup", owner: self,options: nil)!.last as! CuePointPopup
}
override func awakeFromNib() {
self.textFieldWhoText.delegate = self
self.textViewWhatText.delegate = self
self.textFieldWhereText.delegate = self
self.textFieldCueText.delegate = self
textViewWhatText.text = "Hello"
}
func setViewData(cueModel:CuePoint) {
self.cuePointObj = cueModel
labelCueNumberInImage.text = cueModel.cueNumber
labelCueNumber.text = "Cue #:" + cueModel.cueNumber
labelLayerName.text = "Layer #:" + cueModel.layerName
labelPageNumber.text = "Page #:" + cueModel.pageNumber
textFieldPageNumber.text = cueModel.pageNumber
textFieldWhoText.text = cueModel.whoString
textViewWhatText.text = cueModel.whatString
textFieldWhereText.text = cueModel.whereString
textFieldCueText.text = cueModel.cueTextString
if cueModel.isVisibleOnPage == true {
btnOutletVisibleOnPage.setImage(UIImage(named: "SelectedBox"), for: [])
btnOutletVisibleOnPage.tag = 1
}else{
btnOutletVisibleOnPage.setImage(UIImage(named: "UnselectedBox"), for: [])
btnOutletVisibleOnPage.tag = 0
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
if textField.text != "" {
if blockTextChangedForPageNumber != nil {
self.blockTextChangedForPageNumber(textField.text!, self.cuePointObj)
}
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
//self.view.endEditing(true)
if self.textFieldWhoText.isEditing {
self.textFieldWhoText.endEditing(true)
} else if self.textFieldCueText.isEditing{
self.textFieldCueText.endEditing(true)
} else if self.textFieldWhereText.isEditing {
self.textFieldWhereText.endEditing(true)
} else {
self.textViewWhatText.endEditing(true)
}
//self.view.endEditing(true)
return false
}
}
Here is how i load the XIB
#IBOutlet weak var bookView: UIView!
var objCuePopup:CuePointPopup!
if objCuePopup != nil {
objCuePopup.removeFromSuperview()
}
objCuePopup = CuePointPopup.loadNib()
objCuePopup = CuePointPopup.loadNib()
objCuePopup.frame = CGRect(x:cuePointModal.cueX, y:0, width:465, height:410)
objCuePopup.center = CGPoint(x:objCuePopup.center.x, y:cuePointModal.cueY + 5)
//Set Y value for Popup View
if objCuePopup.frame.origin.y < bookView.frame.origin.y {
objCuePopup.frame.origin.y = bookView.frame.origin.y
}
let popupMaxY = objCuePopup.frame.maxY
let bookViewMaxY = bookView.frame.maxY
if popupMaxY > bookViewMaxY {
objCuePopup.frame.origin.y = bookViewMaxY - objCuePopup.frame.size.height
}
//Set X value for Popup View
if cuePointModal.cueX > 455 {
objCuePopup.frame.origin.x = cuePointModal.cueX - 455
objCuePopup.boxArrowLeft.isHidden = true
objCuePopup.boxArrowRight.isHidden = false
let rightY = cuePointModal.cueY - objCuePopup.frame.origin.y
objCuePopup.boxArrowRightTopConstraint.constant = rightY + 3
}else{
objCuePopup.frame.origin.x = cuePointModal.cueX + 40
objCuePopup.boxArrowLeft.isHidden = false
objCuePopup.boxArrowRight.isHidden = true
let leftY = cuePointModal.cueY - objCuePopup.frame.origin.y
objCuePopup.boxArrowLeftTopConstraint.constant = leftY + 3
}
objCuePopup.setViewData(cueModel: cuePointModal)
objCuePopup.textFieldWhoText.delegate = self
objCuePopup.textFieldWhereText.delegate = self
objCuePopup.textViewWhatText.delegate = self
objCuePopup.textFieldCueText.delegate = self
bookView.addSubview(objCuePopup)
I hope that someone here can help me with this problem.

Use of Unresolved Identifier with Segmented Control

I have a scene in my app that I want to do basic math between two slider bars and a segmented control that the user picks. I am trying to do the math between variables under the segmented controls, but Xcode is giving me a (!) stating
Use of unresolved identifier "xxxx"
with whatever variable I'm trying to add.
My code is:
import UIKit
class DopamineCalculator: UIViewController {
//slider outlets
#IBOutlet weak var slider: UISlider!
#IBOutlet weak var sliderone: UISlider!
//segmentoutlet
#IBOutlet weak var segmentoutlet: UISegmentedControl!
//LABELS
//weight label
#IBOutlet weak var weightlabel: UILabel!
//dosage label
#IBOutlet weak var dosagemg: UILabel!
//Drip Rate Answer Label
#IBOutlet weak var dripanswer: UILabel!
//ACTIONS!!
//weight slider action
#IBAction func weightslider(sender: UISlider) {
let weight = Int(sender.value)
//converts to kgs
let kgs = Int(sender.value) / Int(2.2)
weightlabel.text = "\(weight) lbs"
}
//Dosage Desired dosage slider
#IBAction func dosagedesired(sender: UISlider) {
let dosage = Int(sender.value)
dosagemg.text = "\(dosage) mg"
}
//CONCENTRATION OPTIONS
#IBAction func concentrationoption(sender: UISegmentedControl) {
switch segmentoutlet.selectedSegmentIndex
{
case 0:
dripanswer.text = (kgs) * (dosage) / 800
case 1:
dripanswer.text = "1600";
case 2:
dripanswer.text = "3200";
default:
break;
}
}
What I am trying to do is kgs x dosage / 800 respectively for each case. I can not find an adequate solution online to the unresolved identifier issue.
#IBOutlet ...
// Add variables to be reachable for all methods
var dosage : Int = 0
var kgs : Double = 0.0
var divisor : Double = 800.0
#IBAction func dosagedesired(sender: UISlider) {
// prepend self to variable as it is used
self.dosage = Int(sender.value)
dosagemg.text = "\(self.dosage) mg"
// adding the calculation here
let result = self.kgs * Double(self.dosage) / self.divisor
dripanswer.text = "\(result)"
}
#IBAction func weightslider(sender: UISlider) {
let weight = Int(sender.value)
// converts to kgs
// the same here
self.kgs = Int(sender.value) / Int(2.2)
// adding the calculation here
let result = self.kgs * Double(self.dosage) / self.divisor
dripanswer.text = "\(result)"
}
#IBAction func concentrationoption(sender: UISegmentedControl) {
switch segmentoutlet.selectedSegmentIndex
{
case 0:
self.divisor = 800.0
case 1:
self.divisor = 1600.0
case 2:
self.divisor = 3200.0
default:
self.divisor = 800.0
}
// finally the calculation
let result = self.kgs * Double(self.dosage) / self.divisor
dripanswer.text = "\(result)"
}
You should declare the variables kgs and dosage outside of any method i.e. at the class level, along with your outlets
//slider outlets
#IBOutlet weak var slider: UISlider!
#IBOutlet weak var sliderone: UISlider!
//segmentoutlet
#IBOutlet weak var segmentoutlet: UISegmentedControl!
//LABELS
//weight label
#IBOutlet weak var weightlabel: UILabel!
//dosage label
#IBOutlet weak var dosagemg: UILabel!
//Drip Rate Answer Label
#IBOutlet weak var dripanswer: UILabel!
// You should declare the variables here:
var kgs = 0
var dosage = 0
And when you use kgs and dosage inside your methods, remove the word let because you're not declaring a variable.
The reason you do this is that you can't access variables declared in a method in another method. In the concentrationoption method, you can't access dosage, which is defined in dosagedesired method.

Issues with tip calculator app and displaying data

Hey everyone I need some help here with my code
When I select the default tip rate in settings and go back the percentage label appear to be multiplied by 100.
I send an email to a professor and he told me this:
(("It looks like it's because you are saving the default tip rate as "20" instead of "0.20" so when you multiply that by "100" you get "2000" instead of "20"."))) There are a couple ways to solve this, but the easiest would be to divide by 100 when you compute the tip amount.
I will appreciate someones help me making the line of code that I need to divide the amount by 100.
Below I will leave some screenshots of my code.
The screenshot of the Views are in order :
Here is my MainViewController code
import UIKit
class ViewController: UIViewController, SettingsDelegate {
// Inputs
#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!
//Slider & Stepper
#IBOutlet weak var tipSlider: UISlider!
#IBOutlet weak var personsStepper: UIStepper!
//Variables
var tipPercentage : Double = NSUserDefaults.standardUserDefaults().doubleForKey("DefaultTipRate") ?? 0.20
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.
tipAmountLabel.text = "$0.00"
totalBillLabel.text = "Bill Total"
billPerPersonLabel.text = "$0.00"
numberOfPersonLabel.text = "1"
self.amountTextField.becomeFirstResponder()
}
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)
personsStepper.minimumValue = 1
personsStepper.maximumValue = 30
personsStepper.value = 1
personsStepper.addTarget(self, action: "sliderPersonChanged:", forControlEvents: .ValueChanged)
amountTextField.text = ""
refreshCalculation()
}
#IBAction func OnEditingFieldBill(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)"
}
#IBAction func sliderTipChanged(sender: UISlider) {
tipPercentage = Double(round(tipSlider.value)) / 100
refreshCalculation()
}
#IBAction func StepperPersonChanged(sender: UIStepper) {
numberOfPerson = Int(round(personsStepper.value))
refreshCalculation()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let SettingsViewController = segue.destinationViewController as? SettingsViewController {
SettingsViewController.delegate = self
refreshCalculation()
}
}
func tipPercentageChanged(newValue: Double) {
TipPercentageLabel.text = "\(newValue)%"
tipPercentage = newValue
refreshCalculation()
}
}
And here are the Settings View code
import UIKit
protocol SettingsDelegate{
func tipPercentageChanged(newValue : Double)
}
class SettingsViewController: UIViewController {
#IBOutlet weak var tipControl: UISegmentedControl!
var tipRates: Double?
var destName : String!
var delegate :SettingsDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAct
In the Settings View it should be sufficient to change, since you have already given it a correct name of a rate, you should also make it a rate
var tipRate = [5, 10, 15, 20, 25, 30]
to
var tipRate = [0.05, 0.10, 0.15, 0.20, 0.25, 0.30]
You can also get rid of the next line which does the cast to Double, since it is not needed.

Resources