Reset Values After A Calculation + Picker Selection

Hello again. My app calculates as expected in every manner except that when I change the picker options, it internalizes the user input and doesn't allow the user to change inputs anymore. I was thinking about including a reset button, but for a more ideal UI experience, is there a way that after I have the calculate button pressed and it outputs my time, can I have the user selected picker options and input data reset to default values?

Again, I'm new to Swift, so I apologize for basic questions like this, and help is greatly appreciated.

Code Block //
// ScubaViewController.swift
// Navy Diving Air Calculations
//
// Created by Tyler Ault on 5/15/21.
//
import UIKit
class ScubaViewController: UIViewController{
   
  let consumptionScuba:Double = 1.4
  var allowedTime:Double = 0
  var consumptionAir:Double = 0
  var volumeAvailable:Double = 0
  var mmP:Double = 250
  var fv:Double = 0.0
  var cylN:Int = 1
  let data = [
    (title: "Aluminum 100", fv: 0.47 ),
    (title: "Aluminum 80", fv: 0.399),
    (title: "Aluminum 63", fv: 0.319),
    (title: "Aluminum 50", fv: 0.281),
    (title: "Steel 120", fv: 0.526),
    (title: "Steel 100", fv: 0.445),
    (title: "Steel 72", fv: 0.42)
  ]
  let data2 = [
    (title: "One Cylinder", cylN: 1 ),
    (title: "Two Cylinders", cylN: 2 )
  ]
   
  override func viewDidLoad() {
    super.viewDidLoad()
    picker.dataSource = self
    picker.delegate = self
    pickerCyl.dataSource = self
    pickerCyl.delegate = self
     
    picker.tag = 1
    pickerCyl.tag = 2
  }
   
  @IBOutlet var picker: UIPickerView!
  @IBOutlet var plannedDepth: UITextField!
  @IBOutlet var cylinderPSI: UITextField!
  @IBOutlet var timeOutput: UILabel!
  @IBOutlet var pickerCyl: UIPickerView!
   
  @IBAction func btnCalcClicked(){ //The code below this is to perform the necessary air calculations.
     
    let selectedRow = picker.selectedRow(inComponent: 0)
    guard data.indices.contains(selectedRow) else {
      print("selectedRow invalid")
      return
    }
    fv = data[selectedRow].fv
     
    let selectedRow2 = pickerCyl.selectedRow(inComponent: 0)
    guard data2.indices.contains(selectedRow) else {
      print("selectedRow invalid")
      return
    }
    cylN = data2[selectedRow2].cylN
    let depthText = plannedDepth.text ?? "0" //Handle nil textfield
    let value = depthText == "" ? 0.0 : (Double(depthText) ?? 0.0)
     
    consumptionAir = ((value + 33) / 33) * 1.4
    let psiText = cylinderPSI.text ?? "0"
    let value2 = psiText == "" ? 0.0 : (Double(psiText) ?? 0.0)
    volumeAvailable = ((value2 - mmP) / 14.7) * fv * Double(cylN)
    allowedTime = volumeAvailable / consumptionAir
    timeOutput.text = String(allowedTime.truncate(places:0)) + " Minutes"
    //Outputs the time allowed for the dive, in minutes, based on all factors input.
     
  }
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
  }
     
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }
}
extension ScubaViewController: UIPickerViewDataSource {
  func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
  }
   
  func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    switch pickerView.tag {
    case 1:
      return data.count
    case 2:
      return data2.count
    default:
      return 1
    }
  }
}
extension ScubaViewController: UIPickerViewDelegate{
  func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent: Int) -> String? {
    switch pickerView.tag {
    case 1:
      return data[row].title
    case 2:
      return data2[row].title
    default:
      return "Data not found"
    }
   
  }
}
extension Double {
  func truncate(places : Int)-> Double {
    return Double(floor(pow(10.0, Double(places)) * self)/pow(10.0, Double(places)))
  } //This function is designed to allow me truncate the time output. As a safety factor, times are always rounded down, so an easier method was to just truncate the decimal off of "allowedTime"
}


Accepted Answer

when I change the picker options, it internalizes the user input and doesn't allow the user to change inputs anymore.

Sorry, but I do not understand this part.
Do you want to update the value shown in timeOutput automatically?
Or do you just want to set default values to fields and pickers?

If the latter, you just need to call a function which resets values to default:
Code Block
@IBAction func btnCalcClicked(){ //The code below this is to perform the necessary air calculations.
//...
//Outputs the time allowed for the dive, in minutes, based on all factors input.
resetValues()
}
func resetValues() {
allowedTime = 0
consumptionAir = 0
volumeAvailable = 0
//...
picker.selectRow(0, inComponent: 0, animated: false)
pickerCyl.selectRow(0, inComponent: 0, animated: false)
}

If this is not what you mean, please try to explain what you want to do again.
OOPer,


Thanks again for the help. In introduced that code and it works for everything except on my first picker, after I scroll past the first two options, it gives me an "selectedRow Invalid" in the debugger window. I think it has something to do with the fact that my second picker only has two options, so it's only letting me select two options in the first picker as well. Any other options after the first two ("Aluminum 100" and "Aluminum 80") gives me the "selectedRow Invalid". I'm not sure if this is some unintended interaction between my picker functions? I thought under

Code Block    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    switch pickerView.tag {
    case 1:
      return data.count
    case 2:
      return data2.count
    default:
      return 1
    }
  }
}

It would properly initialize both pickers separately.
OOPer,

Found the issue. It had to do with a typo within my "guard" segments. I was missing the selectedRow2 on the second guard statement. Thanks again for the help!
Changed it to:
Code Block      let selectedRow = picker.selectedRow(inComponent: 0)
    guard data.indices.contains(selectedRow) else {
      print("selectedRow invalid")
      return
    }
    fv = data[selectedRow].fv
     
    let selectedRow2 = pickerCyl.selectedRow(inComponent: 0)
    guard data2.indices.contains(selectedRow2) else {
      print("selectedRow invalid")
      return
    }


Reset Values After A Calculation &#43; Picker Selection
 
 
Q