Search code examples
swiftif-statementsegue

Why are my if functions not preventing the segue to the next view controller?


I have a series of if functions that check if two text fields are empty (or just one of them) and if so, present an error message in a label. If both of the text fields are not empty, then it should execute a calculation and then segue to the following view controller and present the value from the equation in a label. However, even with if functions in place that check to see if the text fields are not nil, the segue still gets executed, even if they are nil, as do the error labels. Why are the if functions not preventing this?

@IBAction func CalcFlowRateEnd(_ sender: UIButton) {
  
    let volume = Double(VolTextField.text!)
    let time = Double(SecTextField.text!)
    let units = volumeUnitsPicker4.selectedRow(inComponent: 0)
    var selectedUnit = data[units]

        
        //milliliters error labels
    if selectedUnit == "milliliters" && volume == nil && time == nil {
            volErrorLabel.text = "Enter Volume"
            secErrorLabel.text = "Enter Seconds"}
        
    if selectedUnit == "milliliters" && volume != nil && time == nil {
            secErrorLabel.text = "Enter Seconds"}
        
    if selectedUnit == "milliliters" && volume == nil && time != nil {
            volErrorLabel.text = "Enter Volume"}
        
        
        //milliliters calc
    if selectedUnit == "milliliters" && volume != nil && time != nil{
    
    let volumeConvert = Double(volume!/1000)
    let timeConvert = Double(time! / 60)
    let flowRateMetric = Double(volumeConvert / timeConvert)
    let volumeImperial = Double(volume!/4546)
    let flowRateImperial = Double(volumeImperial / timeConvert)
    let roundedMetric = round(flowRateMetric * 100) / 100.0
    let roundedImperial = round(flowRateImperial * 100) / 100.0
            
    calcFlowRate.text = "\(roundedMetric) liters per min or \(roundedImperial) gal per min"
        
    func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                 
    let flowRate = calcFlowRate.text ?? ""
    let destinationVC = segue.destination as! FlowRateCalcEndViewController
    destinationVC.flowRate = flowRate
            
    }

Solution

  • The prepare(for segue) function should not be nested within your @IBAction function.

    func prepare(for segue) should be overwritten. It's called before the segue is performed so you have a chance to "do something"

    var isFlowRateCalculated = false
    
    @IBAction func CalcFlowRateEnd(_ sender: UIButton) {
        if selectedUnit == "milliliters" && volume != nil && time != nil {
        // logic
    
        isFlowRateCalculated = true
       }
    }
    
    override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
        return isFlowRateCalculated
    }
    
    override func prepare(for segue) {
        // hand off data for view being presented
    }
    

    This doesn't solve your entire problem but it's a step in the right direction. Happy to continue talking about this with you :)

    I also recommend taking a look at this article on Medium