Dynamically Calculate Pace in Swift - ios

I have this code below. How would dynamically calculate the pace as I fill in the fields instead of having to calculate it manually by tapping on the Calculate Pace button?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var minTextField: UITextField!
#IBOutlet weak var secTextField: UITextField!
#IBOutlet weak var distTextField: UITextField!
#IBOutlet weak var paceLabel: UILabel!
func paceInSeconds (minutes:Double, seconds: Double, distance: Double) -> Double {
return ((minutes*60) + seconds) / distance
}
#IBAction func paceCalculator(sender: UIButton) {
var paceMinutes = paceInSeconds(((minTextField.text as NSString).doubleValue, seconds: (secTextField.text as NSString).doubleValue, distance: (distTextField.text as NSString).doubleValue)) / 60
var roundedPaceMinutes = Double(floor(paceMinutes))
var decimalPaceSeconds = paceMinutes - roundedPaceMinutes
var intPaceMinutes = Int(floor(roundedPaceMinutes))
var paceSeconds = Int(floor(decimalPaceSeconds * 60))
var paceSecondsZero = String(format: "%02d", paceSeconds)
paceLabel.text = "\(intPaceMinutes):\(paceSecondsZero)/km"
}
}
Here's the storyboard UI:

You can use the various functions of the UITextFieldDelegate protocol. If you assign your view controller as the delegate of the text field, it will be able to act upon changes in the text field.
In your case, you should implement the textField:shouldChangeCharactersInRange:replacementString: function.

Related

How do I get my new text entry into a UITextfield to store when closing app?

I'm completely new to programming. Trying to learn Swift. I've created the UI for my app. A simple data entry app for weight lifting PB's. However when I close the app my data doesn't update to new stored values. How do assign a variable string to each UITextfield entry, which when I close the app it will display its last stored value?
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var benchPressPB: UITextField!
#IBOutlet weak var squatPB: UITextField!
#IBOutlet weak var deadliftPB: UITextField!
#IBOutlet weak var ohpPB: UITextField!
#IBOutlet weak var rackPullPB: UITextField!
#IBOutlet weak var legPressPB: UITextField!
#IBOutlet weak var pullUpsPB: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.benchPressPB.delegate = self
self.squatPB.delegate = self
self.deadliftPB.delegate = self
self.ohpPB.delegate = self
self.rackPullPB.delegate = self
self.legPressPB.delegate = self
self.pullUpsPB.delegate = self
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
P.S this may completely wrong and long already, but currently its achieving what I want it do, just not saving new inputted data. If there's any shorter way to get the keyboard to hide on return, let me know!
Your current code doesn't do anything with the values a user enters into your text fields.
You should
Set up a model object to hold the values that the user enters.
In your textFieldShouldReturn, collect the user input and save it
into your model.
Decide on how you want to persist your app's state so it restores
when the app is launched. At it's simplest, this could be saving each
string to a different key/value pair in UserDefaults, or grouped
together in a dictionary or an array.
The code might look something like this: (not tested. Not even compiled. It will need cleanup before you can use it:
#IBOutlet weak var benchPressPB: UITextField!
#IBOutlet weak var squatPB: UITextField!
#IBOutlet weak var deadliftPB: UITextField!
#IBOutlet weak var ohpPB: UITextField!
#IBOutlet weak var rackPullPB: UITextField!
#IBOutlet weak var legPressPB: UITextField!
#IBOutlet weak var pullUpsPB: UITextField!
var textFields = [UITextField]
var textFieldKeys = [
"benchPressPB",
"squatPB",
"deadliftPB",
"ohpPB",
"rackPullPB",
"legPressPB",
"pullUpsPB"
]
var textFieldStrings = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Note that you can hook up the delegates for your
// text fields in your Storyboard.
self.benchPressPB.delegate = self
self.squatPB.delegate = self
self.deadliftPB.delegate = self
self.ohpPB.delegate = self
self.rackPullPB.delegate = self
self.legPressPB.delegate = self
self.pullUpsPB.delegate = self
textFields = [benchPressPB, squatPB, deadliftPB, ohpPB, rackPullPB, legPressPB, pullUpsPB]
// Read values from UserDefaults into the text fields.
for (index, key) in textFieldKeys.enumerated() {
let aValue = UserDefaults.standard.string(forKey: key)
textFields[index].text = aValue
textFieldStrings.append(aValue ?? "")
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
let newText = textField.text
if let index = textFields.firstIndex(of: textField) {
textFieldStrings[index] = newText
UserDefaults.standard.set(newText, forKey: textFieldKeys[index])
}
return true
}
You can subclass UITextField and add a target for editing changed. Every time your text changes you can simply save its new value into user defaults. To make sure you use a unique key for each field you can override the accessibilityIdentifier and implement didSet to load the old values when you set its identifier:
import UIKit
class PersistentTextField: UITextField, UITextFieldDelegate {
override var accessibilityIdentifier: String? {
didSet {
text = UserDefaults.standard.string(forKey: accessibilityIdentifier ?? "")
}
}
override func didMoveToSuperview() {
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
autocapitalizationType = .none
autocorrectionType = .no
delegate = self
}
#objc func editingChanged(_ textField: UITextField) {
UserDefaults.standard.set(text ?? "", forKey: accessibilityIdentifier ?? "")
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
resignFirstResponder()
return true
}
}
Then in your view controller just make sure to set their id when your view loads:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var benchPressPB: PersistentTextField!
#IBOutlet weak var squatPB: PersistentTextField!
#IBOutlet weak var deadliftPB: PersistentTextField!
#IBOutlet weak var ohpPB: PersistentTextField!
#IBOutlet weak var rackPullPB: PersistentTextField!
#IBOutlet weak var legPressPB: PersistentTextField!
#IBOutlet weak var pullUpsPB: PersistentTextField!
override func viewDidLoad() {
super.viewDidLoad()
benchPressPB.accessibilityIdentifier = "bench press"
squatPB.accessibilityIdentifier = "squat"
deadliftPB.accessibilityIdentifier = "dead lift"
ohpPB.accessibilityIdentifier = "ohp"
rackPullPB.accessibilityIdentifier = "rack pull"
legPressPB.accessibilityIdentifier = "leg press"
pullUpsPB.accessibilityIdentifier = "pull ups"
}
}

Looking to accept user input, and calculate a running total - Swift 5/Xcode

I am a beginner working on an app that will function like a golf scorecard. My first issue has come while attempting to accept user input in a (prototype) series of 9 textFields so the user can type in their scores, and then a textView at the end that is not editable that will show the total for the 9 holes. I am trying to get this to be a running total that updates constantly.
I tried passing the inputs from each textField into an array, and returning the sum of the array to a the textView, but still had issues with the data type from the textField being a string, where as I will only be dealing with integers.
My clunky first pass is as follows -
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var holeOneScore: UITextField!
#IBOutlet weak var holeTwoScore: UITextField!
#IBOutlet weak var holeThreeScore: UITextField!
#IBOutlet weak var holeFourScore: UITextField!
#IBOutlet weak var holeFiveScore: UITextField!
#IBOutlet weak var holeSixScore: UITextField!
#IBOutlet weak var holeSevenScore: UITextField!
#IBOutlet weak var holeEightScore: UITextField!
#IBOutlet weak var holeNineScore: UITextField!
#IBOutlet weak var totalForFrontNine: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//MARK: Calculate Scores
#IBAction func calculate(_ sender: Any) {
let hole1:Int = Int(holeOneScore.text!)!
let hole2:Int = Int(holeTwoScore.text!)!
let hole3:Int = Int(holeThreeScore.text!)!
let hole4:Int = Int(holeFourScore.text!)!
let hole5:Int = Int(holeFiveScore.text!)!
let hole6:Int = Int(holeSixScore.text!)!
let hole7:Int = Int(holeSevenScore.text!)!
let hole8:Int = Int(holeEightScore.text!)!
let hole9:Int = Int(holeNineScore.text!)!
let totalArray = [hole1, hole2, hole3, hole4, hole5, hole6, hole7, hole8, hole9]
let totalScore = totalArray.reduce(0, +)
totalForFrontNine.text = String(totalScore)
print(totalForFrontNine!)
}
It worked, but barely. Any thoughts to modify this or a complete refresh is fine! I am not tied to anything as i am using this project to just teach me the basics.
Thanks in advance, cheers - glassGarrett
Like #jawadali mentioned, use IBOutletCollection. Here is a tutorial about how to use it.
As for the other issue,
...the data type from the textField being a string, where as I will only be dealing with integers.
A quick solution is to set the keyboardType of your textfield to UIKeyboardTypeNumberPad, or .numberPad in Swift.
textField.keyboardType = .numberPad
Or in storyboard,

Adding thousands separators to UILabel numbers

I'm trying to add thousands separators on the numbers exporting out of two UILabels on my code. I've already searched for it on here but none works for my project.
here's the part about calculation in my code so far:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var userCount: UITextField!
#IBOutlet weak var resultLabel: UILabel!
#IBOutlet weak var projectAmount: UITextField!
#IBOutlet weak var totalLabel: UILabel!
#IBAction func polculateButton(_ sender: Any) {
let usersCount = Double(self.userCount.text ?? "") ?? 0
let commissionPercentage = 0.26
let projectsAmount = Double(self.projectAmount.text ?? "") ?? 0
let totalsLabel = (usersCount * projectsAmount)
self.totalLabel.text = "\(totalsLabel)"
let resultsLabel = (usersCount * commissionPercentage * projectsAmount)
self.resultLabel.text = "\(resultsLabel)"
}
}
What code should I add here?

Bill Amount for Tip Calc. is not influencing tip and total #'s

Below is my code and a picture. I have looked at previous questions regarding smilier issues but could not find help.
Furthermore, where in my code is the error in which when I enter a number in the bill field it should begins to calculate the tip amount and fill in the tip and total numbers?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var billField: UITextField!
#IBOutlet weak var tipLabel: UILabel!
#IBOutlet weak var totalLabel: UILabel!
#IBOutlet weak var tipControl: UISegmentedControl!
#IBAction func onTap(sender: AnyObject){
view.endEditing(true)
}
#IBAction func calculateTip(sender: AnyObject) {
let tipPercentages = [0.18, 0.2, 0.25]
let bill = Double(billField.text!)!
let tip = bill * tipPercentages[tipControl.selectedSegmentIndex]
let total = bill + tip
tipLabel.text = String (format: "$%.2f", tip)
totalLabel.text = String (format: "$%.2f", tip)
}
}

Converting UILabel Variables to Double variables in Swift 2

I am currently trying to convert two UILabel variables to Doubles. this is what I am currently trying:
#IBOutlet weak var longitude: UILabel!
#IBOutlet weak var latitude: UILabel!
var longitude_dbl = Double(longitude)
var latitude_dbl = Double(latitude)
Any help would be great.
Try this: First, check if you have the value in your UILabel's text property.
#IBOutlet weak var longitude: UILabel!
#IBOutlet weak var latitude: UILabel!
var longitude_dbl: Double?
var latitude_dbl: Double?
func setCoordinateValues() {
guard let longitudeValue = longitude.text, latitudeValue = latitude.text else {
return
}
longitude_dbl = Double(longitudeValue)
latitude_dbl = Double(latitudeValue)
}
Before that make sure, your labels are hooked up properly in the XIB/storyboard.

Resources