Is it possible to toss data to another view controller? - ios

I just Make timer that can use in life. just like image that I push in here, if I go back to main ViewController then I wanna the number that I input in set view controller are tossed to viewController so when I go back to main ViewController and press restart then that number gonna be in text of CountTimeLabel.. but I really don't know how to toss data that I input in another view controller to root viewController... pleas help me.. if I write code like ViewController().variableName = 30 in setViewController, that dose not make things well..(I already know about prepare function but that is not what I am finding..because this is happen when I go back to ViewController(RootViewController)) I will put my code in below..
is it possible to toss data to another view controller from other view controller?
import UIKit
class ViewController: UIViewController{
#IBOutlet var AllTileLabel: UILabel!
#IBOutlet var SumTimeLabel: UILabel!
#IBOutlet var CountTimeLabel: UILabel!
#IBOutlet var StartButton: UIButton!
#IBOutlet var StopButton: UIButton!
#IBOutlet var ResetButton: UIButton!
var timeTrigger = true
var realTime = Timer()
var second : Int = 3000
var sum : Int = 14400
var allTime : Int = 14400
var IntSecond : Int = 0
var ifReset = false
override func viewDidLoad() {
StartButton.layer.cornerRadius = 10
StopButton.layer.cornerRadius = 10
ResetButton.layer.cornerRadius = 10
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func StartButtonAction(_ sender: UIButton) {
if timeTrigger { checkTimeTrigger() }
print("Start")
}
#IBAction func StopButtonAction(_ sender: UIButton) {
endGame()
}
#IBAction func ResetButtonAction(_ sender: UIButton) {
print(second)
getTimeData()
//second = 3000
//CountTimeLabel.text = "0:50:00"
CountTimeLabel.text = printTime(temp: second)
ifReset = true
}
#IBAction func Reset(_ sender: UIButton) {
endGame()
timeTrigger = true
realTime = Timer()
second = 3000
sum = 14400
allTime = 14400
IntSecond = 0
ifReset = false
AllTileLabel.text = "8:00:00"
SumTimeLabel.text = "0:0:0"
CountTimeLabel.text = "0:50:00"
}
#objc func updateCounter(){
// if String(format: "%.2f",second) == "0.00"{
if second < 1 {
endGame()
CountTimeLabel.text = "종료"
} else {
second = second - 1
sum = sum + 1
allTime = allTime - 1
AllTileLabel.text = printTime(temp: allTime)
SumTimeLabel.text = printTime(temp: sum)
CountTimeLabel.text = printTime(temp: second)
print("update")
}
}
func checkTimeTrigger() {
realTime = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
timeTrigger = false
}
func endGame() {
realTime.invalidate()
timeTrigger = true
}
func printTime(temp : Int) -> String
{
let S = temp%60
let H = temp/3600
let M = temp/60 - H*60
let returnString = String(H) + ":" + String(M) + ":" + String(S)
return returnString
}
func getTimeData() {
second = 20
sum = SetViewController().real.sum
allTime = SetViewController().real.allTime
print(second)
}
}
import UIKit
class SetViewController: UIViewController {
#IBOutlet var View1: UIView!
#IBOutlet var View2: UIView!
#IBOutlet var InputView1: UIView!
#IBOutlet var InputView2: UIView!
#IBOutlet var SetButton: UIButton!
#IBOutlet var H1TextField: UITextField!
#IBOutlet var M1TextField: UITextField!
#IBOutlet var H2TextField: UITextField!
#IBOutlet var M2TextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
H1TextField.keyboardType = .numberPad
M1TextField.keyboardType = .numberPad
H2TextField.keyboardType = .numberPad
M2TextField.keyboardType = .numberPad
View1.layer.cornerRadius = 14
View2.layer.cornerRadius = 14
InputView1.layer.cornerRadius = 10
InputView2.layer.cornerRadius = 10
SetButton.layer.cornerRadius = 10
// Do any additional setup after loading the view.
}
#IBAction func SetButton(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
enter image description here

If you're a hobbyist programmer and you just want to "get it done", simply use a static.
Let's say Bottom: UIViewController is the "main", root, view controller at the absolute "base" of your app. no matter what happens "Bottom" is always there.
Say Timer: UIViewController is (any) other view controller you put on top for some reason.
In Bottom, do this
class Bottom: UIViewController, etc ... {
static weak var current: Bottom? = nil
override func viewDidLoad() {
super.viewDidLoad()
Bottom.current = self
}
func testing() {
print("it works, WTH")
}
Note that in ViewDidLoad, you simply set it.
Next, say you are in Timer, try this:
class Timer: UIViewController, etc ... {
func someFunction() {
Bottom.current.testing() // it's that easy
}
It's that easy.
Note there is a huge amount of confusion about using statics, singletons, and similar approaches in iPhone programming.
(Just for example, many engineers will say "avoid singletons!" This is remarkably confused because in iOS engineering, almost everything is a singleton (notably the app itself (!!!!!), the screen, the GPS, etc etc.)
In any event, as a beginner hobbyist, learn how to use statics (it's simple .. Bottom.current. ... as above), and eventually you can learn about the pros and cons of such things.

Related

Why isn't the score showing up after segue on different view controller?

Iv created a quiz app, that tracks the user's score till the user gets to the end. There is an if statement - when it reaches the end of the quiz, a results View controller pops up. My Question is I want to get the same score value presented at the end on the resultsViewContoller. I have connected it via segue and the identifier has been placed. The app runs but when i get to the end the segue opens up the page but the score doesnt change?
How can i solve this problem?
The user finishes the app. I call the segue method and the screen comes up.
Results View Controller
import UIKit
class ResultsViewController: UIViewController {
var fruitness = Fruitness()
#IBOutlet weak var finalScoreLabel: UILabel!
var finalScore: String!
override func prepare(for: UIStoryboardSegue, sender: Any?) {
func viewWillAppear(_ animated: Bool) {
finalScoreLabel.text = finalScore
if finalScore != nil {
finalScoreLabel.text = "FINALSCORE:\(String(describing: Int(finalScore!)))"
}
}
}
}
Game View Controller
import UIKit
class GameViewController: UIViewController {
#IBOutlet weak var progressBar: UIProgressView!
#IBOutlet private weak var fruitLabel: UILabel!
#IBOutlet private weak var scoreLabel: UILabel!
#IBOutlet weak var replayGame: UIButton!
#IBOutlet weak var optionButton0: UIButton!
#IBOutlet weak var optionButton1: UIButton!
#IBOutlet weak var optionButton2: UIButton!
#IBOutlet weak var optionButton3: UIButton!
#IBOutlet weak var optionButton4: UIButton!
#IBOutlet weak var optionButton5: UIButton!
#IBOutlet weak var optionButton6: UIButton!
#IBOutlet weak var optionButton7: UIButton!
#IBOutlet weak var optionButton8: UIButton!
#IBOutlet private var fruitButtons: [UIButton]!
var score = 0
var fruitness = Fruitness()
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
#IBAction func replayGame(_ sender: UIButton) {
fruitness.restartGame() //Calling restart
updateUI()
}
#IBAction func touchButton(_ sender: UIButton) {
let userAnswer = sender.currentTitle!
//The userGotItRight is = to the checkAnswer function which goes through the fruitOptions array to make sure the answer is corrct. T/F
let userGotItRight = checkAnswer(userAnswer: userAnswer)
if userGotItRight {
//Depending if the user got the answer correct the button turns green/red
sender.backgroundColor = UIColor.green
} else {
sender.backgroundColor = UIColor.red
}
nextFruit() //Calling the next Fruit untill all the fruit items have been displayed.
//This timer is responsible for the UIColors green, red and clear. Without this timer the color drags onto the next fruit.
Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(updateUI), userInfo:nil, repeats: false)
}
// This check answer method needs an input to work. The input is the answer the user-choose (String).
func checkAnswer(userAnswer: String) -> Bool {
// Checks if the user got the answer correct. T/F
if userAnswer == fruitness.fruitOptions[fruitness.fruitNumber].fruit {
fruitness.score += 1 //We increase the value of score when we get the answer right.
// fruitness.finalScorez = fruitness.score
return true
} else {
return false
}
}
//Checks to make sure the eveytime it hits 0 it will shuffle.
func nextFruit() {
if fruitness.fruitNumber == 0 {
fruitness.fruitOptions.shuffle()
}
// print(fruitness.fruitOptions[fruitness.fruitNumber]) //Only gets printed in the consol
if fruitness.fruitNumber + 1 < fruitness.fruitOptions.count {
fruitness.fruitNumber += 1
} else {
self.performSegue(withIdentifier: "goToResultsVC", sender: self) //To call Segue
}
}
//Connecting and controlling oF the Segue and from GameView COntroller -> Results view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToResultsVC" {
let destinationVC = segue.destination as! ResultsViewController
destinationVC.finalScore = scoreLabel.text //Printing the final score at the end.
}
}
#objc func updateUI() {
//Controlls the background. Clearing ability between T/F answers.
optionButton0.backgroundColor = UIColor.clear
optionButton1.backgroundColor = UIColor.clear
optionButton2.backgroundColor = UIColor.clear
optionButton3.backgroundColor = UIColor.clear
optionButton4.backgroundColor = UIColor.clear
optionButton5.backgroundColor = UIColor.clear
optionButton6.backgroundColor = UIColor.clear
optionButton7.backgroundColor = UIColor.clear
optionButton8.backgroundColor = UIColor.clear
//The fruit name available that the user needs to match.
fruitLabel.text = fruitness.getFruitText()
//Displaying the progress of the user till they reach the end.
progressBar.progress = fruitness.getProgress()
//Displaying the score at all times
scoreLabel.text = "SCORE: \(fruitness.score)"
}
}
You have a number of problems with your code.
First off, the prepare(for:sender:) method gets called on the source view controller that triggers the segue, not the destination view controller.
Second, your ResultsViewController has a viewWillAppear(_:) method nested inside its prepare(for:sender:) method. Don't do that. The viewWillAppear(_:) method needs to be a top-level method of your view controller or it won't get called.
Also, viewWillAppear(_:) methods should call super.viewWillAppear(animated).
Your ResultsViewController's viewWillAppear method should look like this:
func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
finalScoreLabel.text = finalScore
}
The prepare(for:sender:) method in your GameViewController should set finalScore in your ResultsViewController so that when its viewWillAppear is called, finalScore has a value.
Edit:
(It looks like you got that last part correct. Your GameViewController's prepare(for:sender) does appear to set finalScore. Note, however, that you are using scoreLabel to hold your finalScoreValue. You should not save state in view objects. You should have a var in GameViewController that holds your score. You could make GameViewController set your score var, and have a didSet() method on the score var that installs the updated score value into the scoreLabel.)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToResultsVC" {
let destinationVC = segue.destination as! ResultsViewController
destinationVC.finalScore = scoreLabel.text //Printing the final score at the end.
}
}
Maybe you wish to refactor your repetitive code to this one:
let optionButtonArray = [optionButton0,optionButton1 ...]
optionButtonArray.forEach { $0.backgroundColor = UIColor.clear }

Swift NSTiimer not following specified Interval

I am trying to create a quiz app which has a timer for each question when the timer expires (i.e. 10 seconds and I want Timer to have an interval of 1 sec) it resets it self and next question is fetched and Timer again restart from 10... But my issue is the timer doesn't follow a fixed interval when first question is loaded it shows interval of 2 ... i.e. 10,8,6 .. and then for second question it makes jump for 3 secs interval and similarly the interval increases.
import UIKit
class ViewController: UIViewController {
let allQuestions = QuestionsBundle()
var pickedAnswer : Int = 0
var questionCounter = 0
var score : Int = 0
var timer: Timer!
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var countDownLabel: UILabel!
#IBOutlet weak var ansLbl1: UILabel!
#IBOutlet weak var ansLbl2: UILabel!
#IBOutlet weak var ansLbl3: UILabel!
#IBOutlet weak var ansLbl4: UILabel!
#IBOutlet weak var checkBox1: CheckBox!
#IBOutlet weak var checkBox2: CheckBox!
#IBOutlet weak var checkBox3: CheckBox!
#IBOutlet weak var checkBox4: CheckBox!
var checkBoxlist : [CheckBox] = []
#IBAction func correct_Answer_Checbox_Btn(_ sender: AnyObject) {
//print("\(sender.tag) <==> \(String(describing: question?.correctAnswer))")
updateCheckBoxes(sender: sender)
if sender.tag == question?.correctAnswer{
question?.isAnswerCorrect = true
question?.selectedAnswer = sender.tag
//score = score + 1
}
else {
question?.isAnswerCorrect = false
}
}
func updateCheckBoxes(sender: AnyObject){
for checkBoxItem in checkBoxlist{
if checkBoxItem.tag != sender.tag {
checkBoxItem.isChecked = false
}
}
}
#IBOutlet weak var nextButton: UIButton!
#IBAction func nextBtnClicked(_ sender: AnyObject) {
do{
try handleNextQuestion()
}
catch{
moveToResultView()
}
}
func handleNextQuestion() throws {
nextQuestion()
if questionCounter == allQuestions.list.count-1{
finishButton.isHidden = false
nextButton.isHidden = true
//scoreLbl.text = "\(score)"
}
}
var question : Question?
var countTime = 10.0
override func viewDidLoad() {
super.viewDidLoad()
finishButton?.isHidden = true
checkBoxlist = fetchCheckBoxList()
question = fetchQuestion()
setQuizView(question: question!)
// Do any additional setup after loading the view, typically from a nib.
}
// set all questions in a function
#objc func update() {
if(countTime > 0) {
countTime = countTime - 1
self.countDownLabel.text = String(countTime)
}else{
timer.invalidate()
countTime = 10.0
do{
try handleNextQuestion()
}
catch{
moveToResultView()
}
}
}
func startTimer() {
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(ViewController.update), userInfo: nil, repeats: true)
}
func setQuizView(question:Question) {
self.countDownLabel.text = "10"
startTimer()
questionLabel.text = question.questionText
ansLbl1.text = question.answer1
ansLbl2.text = question.answer2
ansLbl3.text = question.answer3
ansLbl4.text = question.answer4
if question.selectedAnswer == Constants.DEFAULT_ANSWER {
for checkBoxItem in checkBoxlist{
checkBoxItem.isChecked = false
}
}
}
#IBOutlet weak var finishButton: UIButton!
// prepare segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == resultScreenIdentifier{
let vc = segue.destination as! ResultViewController
vc.data = sender as! String
}
}
let resultScreenIdentifier = "resultScreenSegue"
func moveToResultView(){
performSegue(withIdentifier: resultScreenIdentifier, sender: score)
}
#IBAction func finishButtonClicked(_ sender: UIButton) {
//perform segue
let score = "\(calculateScore())"
moveToResultView()
}
// calculate the score of quiz using loop
func calculateScore()->Int{
var numOfCorrectAnswers = 0
for question in allQuestions.list{
if question.isAnswerCorrect {
numOfCorrectAnswers = numOfCorrectAnswers + 1
//print(numOfCorrectAnswers)
}
}
return numOfCorrectAnswers
}
func nextQuestion(){
showResultView(isCorrect: (question?.isAnswerCorrect)!)
questionCounter = questionCounter + 1
question = fetchQuestion()
setQuizView(question: question!)
}
func fetchQuestion() -> Question{
return allQuestions.list[questionCounter]
}
func fetchCheckBoxList() -> [CheckBox]{
let arr : [CheckBox] = [checkBox1,checkBox2,checkBox3,checkBox4]
return arr
}
}
Timers are not particularly accurate. They can suffer from significant jitter.
A better approach is to create a Date that represents the expiration time (ie Date(timeIntervalSinceNow:10) and then run a Timer with a much shorter interval (I would suggest around 0.1 second). You can then calculate the time remaining based on the target Date and check if the target date is in the past.

Problems Updating View with Swift 5

I am having some trouble updating my secondViewController view in Xcode using Swift 5. I want my app to add two numbers together and show the result in the second ViewController. Although it works the first time, if I return to my previous view and change the numbers, the view does not update.
I tried using viewWillAppear, viewWillDisappear, amongst others, including NSNotificationCenter addObserve, but I have had no luck whatsoever.
Do you have any recommendations? Am I missing something?
Please see below for the code and a screenshot of my ViewControllers:
//
// ViewController.swift
//
import UIKit
var result = ""
var resultFinal = Float(result)
let finalResult = resultFinal!
class ViewController: UIViewController {
#IBOutlet weak var firstNumber: UITextField!
#IBOutlet weak var secondNumber: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func getResult()-> Float{
guard let fNumber = firstNumber.text else {
return 0
}
let firstFloat = Float(fNumber)
guard let sNumber = secondNumber.text else {
return 0
}
let secondFloat = Float(sNumber)
let sumNumber: Float = firstFloat! + secondFloat!
return sumNumber
}
#IBAction func submitSum(_ sender: Any) {
resultFinal = getResult()
print(resultFinal!)
}
}
//
// secondViewController.swift
//
import UIKit
class secondViewController: UIViewController {
#IBOutlet weak var test: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.test.text!=""
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
test.text = String(finalResult)
}
}
Screenshot:
Thanks.
Your problem is with the global variables. It seems from your code that you expect these three to reevaluate every time one of them changes:
var result = ""
var resultFinal = Float(result)
let finalResult = resultFinal!
For example, if you set resultFinal = 4, then finalResult will equal 4. However, those variables only evaluate once––the first time. You can simplify your use of these variables significantly. Replace these three with:
var result: Float?
Then, in ViewController:
class ViewController: UIViewController {
#IBOutlet weak var firstNumber: UITextField!
#IBOutlet weak var secondNumber: UITextField!
func getResult() -> Float {
guard let number1 = Float(firstNumber.text ?? "0") ?? 0
guard let number2 = Float(secondNumber.text ?? "0") ?? 0
return number1 + number2
}
#IBAction func submitSum(_ sender: Any) {
result = getResult()
}
}
Note: I simplified getResult and made it treat empty fields as 0.
In SecondViewController:
class SecondViewController: UIViewController {
#IBOutlet weak var test: UITextField!
override func viewWillAppear(_ animated: Bool) {
test.text = String(result ?? 0)
}
}
Note: self.test.text!="" doesn't really do anything, so I removed it.

Accessing variables in other ViewControllers Swift 3

I have a problem I can't seem to solve myself, I have two view controllers, the first one contains three variables that stores integers. On my second view controller I have 3 sliders which manipulates a label under each slider with a number.
I want the numbers from these 3 sliders to replace the numbers that were set in the three variables on my first view controller when I click a button on the second view controller but when I when I type in the variable name it doesn't show up in the second view controller?
Can somebody explain what I may be doing wrong as I thought the variables were public and globally accessible throughout my app but I'm struggling to figure out what I'm doing wrong.
Here is some of my code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var timer = Timer()
var softTime = 180
var mediumTime = 300
var hardTime = 600
var chosenTime = 0
I want softTime, mediumTime & hardTime to be changed from the button in the next view controller:
import UIKit
class SettingsViewController: UIViewController {
#IBOutlet weak var softLabel: UILabel!
#IBOutlet weak var softSliderValue: UISlider!
#IBAction func softSlider(_ sender: Any) {
let currentValue = Int(softSliderValue.value)
softLabel.text = "\(currentValue)"
}
#IBOutlet weak var mediumLabel: UILabel!
#IBOutlet weak var mediumSliderValue: UISlider!
#IBAction func mediumSlider(_ sender: Any) {
let currentValue = Int(mediumSliderValue.value)
mediumLabel.text = "\(currentValue)"
}
#IBOutlet weak var hardLabel: UILabel!
#IBOutlet weak var hardSliderValue: UISlider!
#IBAction func hardSlider(_ sender: Any) {
let currentValue = Int(hardSliderValue.value)
hardLabel.text = "\(currentValue)"
}
#IBAction func setTimesButton(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
//in Second VC
protocol PassDataDelegte: class {
func your method(first: String, second: String, third: String)
}
weak var delegate: PassDataDelegte?
func youction button() {
delegate?.yourmethod(first, timeString: second, third: date)
}
// in First VC
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DeadlineSegue" {
let dvc = segue.destinationViewController as! YourSecondViewController
dvc.delegate = self
}
}
extension YourFirstViewController: PassDataDelegte {
func sendDateTime((first: String, second: String, third: String) {
print(first)
print(second)
print(third)
}

Passing Data Through Segue & some errors

Hey guys I need some one to help me finish my app, I need to finish it before Dec 15. I'm making a Tip Calculator Project in Swift2 and It must have a settings view where I select the default tip rate. I have some issues with passing data, when I select a default tip percentage it doesn't change in the View Controller, also I want to make the app remember the default rate when I close the app and reopened. I will really appreciate that some one corrects my code and test it. Im new in this, below is the code of the two ViewControllers and a screenshot of the Main.Storyboard (Image 1) (ViewController Screenshot)
My apologies for my bad English, is not my native language
ViewController
import UIKit
class ViewController: UIViewController {
//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 = 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"
TipPercentageLabel.text = "20.0%"
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: AnyObject) {
tipPercentage = Double(round(tipSlider.value)) / 100
refreshCalculation()
}
#IBAction func StepperPersonChanged(sender: AnyObject) {
numberOfPerson = Int(round(personsStepper.value))
refreshCalculation()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let id = segue.identifier {
if id == "show settings" {
if let SettingsViewController = segue.destinationViewController as? SettingsViewController {
}
}
}
}
}
Settings View Controller
import UIKit
class SettingsViewController: UIViewController {
#IBOutlet weak var tipControl: UISegmentedControl!
var tipRates:Double?
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.
}
#IBAction func DefaultRate(sender: AnyObject) {
var tipRate = [5, 10, 15, 20, 25, 30]
var tipRates = Double(tipRate[tipControl.selectedSegmentIndex])
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let id = segue.identifier {
if id == "goBackToViewController" {
if let ViewController = segue.destinationViewController as? ViewController {
if let tip = tipRates {
ViewController.tipPercentage = tip/100
}
}
}
}
---- Edit from comments ----
I think the reason it is not updating as you would like is due to a minor error with this line.
var tipRates = Double(tipRate[tipControl.selectedSegmentIndex])
Inside of your DefaultRate action function for the UISegmentedControl
Using var is a redeclaration of the same variable name, thus what you are trying to pass in the prepareForSegue is an empty variable.
This function should be changed to:
#IBAction func DefaultRate(sender: AnyObject) {
var tipRate = [5, 10, 15, 20, 25, 30]
tipRates = Double(tipRate[tipControl.selectedSegmentIndex])}
Hopefully this will now solve the error.
---- End Edit ----
From what I can see in the viewDidLoad function of your viewController, you are setting the tip label, and not updating the value based on the variable var tipPercentage.
TipPercentageLabel.text = "20.0%"
is setting the value display to always be 20.0%, you could use this here.
var tipDisplay = tipPercentage * 100
TipPercentageLabel.text = "\(tipDisplay)%"
This should update the displayed value in the label, however you never call on your other functions to recalculate the amount etc.
Thus you should also be calling on
func setupContainer()
or
func refreshCalculation()
within your ViewDidLoad().
In terms of remembering the default value when the app is closed you should look into using NSUserDefaults.
Some information regarding NSUserDefaults can be found here, which explains implementing small amounts of saved data and can be implemented in your case quite simply.

Resources