Picker View Data used elsewhere

I apologize in advance, as I'm very new to Swift programming and Xcode, but I'm trying to build an application for my Senior Project in school. My issue stems from being able to use data from a picker view to then assign a value to a variable, based on what was selected in the picker view. For example, when "Aluminum 80" is selected in picker view, I want it to assign 0.399 to the FV variable. I'm not sure how to accomplish this, and I've tried multiple different methods, but nothing seems to work. I thought it would work directly from "data" and using my if...else structure, but it's just defaulting to the 0 that I initialized FV too earlier.

I'd also like to apologize if my code looks sloppy, as I'm still learning. My segment button is still a work in progress. Everything else works as intended though. Thanks in advance
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:Double = 1
  let data = ["Aluminum 100", "Aluminum 80", "Aluminum 63", "Aluminum 50", "Steel 120", "Steel 100", "Steel 72"]
   
  override func viewDidLoad() {
    super.viewDidLoad()
    picker.dataSource = self
    picker.delegate = self
  }
   
  @IBOutlet var picker: UIPickerView!
  @IBOutlet var plannedDepth: UITextField!
  @IBOutlet var cylinderPSI: UITextField!
  @IBOutlet var timeOutput: UILabel!
  @IBAction func didChangeSegment (_ sender: UISegmentedControl){
    if sender.selectedSegmentIndex == 0 {
      cylN = 1
    }
    else if sender.selectedSegmentIndex == 1 {
      cylN = 2
    }
  }
  @IBAction func btnCalcClicked(){ //The code below this is to perform the necessary air calculations. The if...else structure assigns the appropriate floodable volume dependant on the air cylinder type and size selected from the picker, and then assigns the value from the string to FV. The calculations below this plug in all other necessary values
    if data == ["Aluminum 100"]{
      FV = 0.47
    }else if data == ["Aluminum 80"]{
      FV = 0.399
    }else if data == ["Aluminum 63"]{
      FV = 0.319
    }else if data == ["Aluminum 50"]{
      FV = 0.281
    }else if data == ["Steel 120"]{
      FV = 0.526
    }else if data == ["Steel 100"]{
      FV = 0.445
    }else if data == ["Steel 72"]{
      FV = 0.42
    }
    consumptionAir = Double(((Double(plannedDepth.text!)! + 33)/33)) * 1.4
    volumeAvailable = Double((Double(cylinderPSI.text!)! - mmP) / 14.7) * FV * cylN
    allowedTime = volumeAvailable / consumptionAir
    timeOutput.text = String(allowedTime) //Outputs the time allowed for the dive, in minutes, based on all factors input.
  }
     
  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }
}
extension ScubaViewController: UIPickerViewDataSource {
  func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
  }
   
  func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return data.count
  }
}
extension ScubaViewController: UIPickerViewDelegate{
  func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent: Int) -> String? {
    return data[row]
  }
}


Accepted Answer
In your ScubaViewController, the property data is initialized with an Array of 7 elements and it cannot be modified.
Thus, any of the conditions of your if-statements never get true.

You need to get the selected value from picker.
An example:
Code Block
@IBAction func btnCalcClicked() {
let selectedRow = picker.selectedRow(inComponent: 0)
guard data.indices.contains(selectedRow) else {
print("selectedRow invalid")
return
}
let selectedData = data[selectedRow]
if selectedData == "Aluminum 100" {
fv = 0.47
} else if selectedData == "Aluminum 80" {
fv = 0.399
} else if selectedData == "Aluminum 63" {
fv = 0.319
} else if selectedData == "Aluminum 50" {
fv = 0.281
} else if selectedData == "Steel 120" {
fv = 0.526
} else if selectedData == "Steel 100" {
fv = 0.445
} else if selectedData == "Steel 72" {
fv = 0.42
}
consumptionAir = Double(((Double(plannedDepth.text!)! + 33)/33)) * 1.4
volumeAvailable = Double((Double(cylinderPSI.text!)! - mmP) / 14.7) * fv * cylN
allowedTime = volumeAvailable / consumptionAir
timeOutput.text = String(allowedTime) //Outputs the time allowed for the dive, in minutes, based on all factors input.
}

(I have renamed FV to fv, as in Swift, only type names start with Capital letter.)


But writing bunch of if-statements is not preferred.

I would write something like this:
Code Block
class ScubaViewController: UIViewController {
//...
var fv: Double = 0.0
//...
let data = [ //# Give this a better name than `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)
]
//...
@IBOutlet var picker: UIPickerView!
//...
@IBAction func btnCalcClicked() {
let selectedRow = picker.selectedRow(inComponent: 0)
guard data.indices.contains(selectedRow) else {
print("selectedRow invalid")
return
}
fv = data[selectedRow].fv
//...
}
//...
}
//...
extension ScubaViewController: UIPickerViewDelegate{
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent: Int) -> String? {
return data[row].title
}
}


With the present code:
Code Block
  let data = ["Aluminum 100", "Aluminum 80", "Aluminum 63", "Aluminum 50", "Steel 120", "Steel 100", "Steel 72"]

when you test:
Code Block
    if data == ["Aluminum 100"]{

you test in fact:
Code Block
    if ["Aluminum 100", "Aluminum 80", "Aluminum 63", "Aluminum 50", "Steel 120", "Steel 100", "Steel 72"] == ["Aluminum 100"]{

So that is false. OOPer explained how to solve.

Note that you can streamline your formulas:
consumptionAir = (Double(plannedDepth.text!) + 33) / 33 * 1.4

But you need to make it more robust: if text is empty or nil, you'll crash

Code Block
let depthText = plannedDepth.text ?? "0" // Handle nil textField
let value = depthText == "" ? 0.0 : (Double(depthText) ?? 0.0) // Handle empty textField: value is zero ; and if text is not a num (eg: "abcd", also zero
consumptionAir = (value + 33) / 33 * 1.4 // No more risk of crash


For timeOutput.text,
you should at least show the unit and better convert to hours and minutes.
OOPer,

Really appreciate the help; that did the trick. My brain wasn't registering that I had defined the data in an array and wouldn't be able to change it. Thank you!

Claude31,

Thanks for the advice on avoiding crashes. I hadn't got that yet, but that was going to be information I was also going to have to hunt down.
Picker View Data used elsewhere
 
 
Q