Search code examples
swiftviewbooleanprogress

Progress bar to fill percentage when textfields are entered in Swift 4


I am making an app for learning purposes that has static cells and I have a progress bar at the top of the view that I want to start at zero. When they fill in all fields it completes the progress bar and then a button appears saying save. I thought this way would work.

import UIKit

class TableViewController: UITableViewController {


    @IBOutlet var infoProgressBar: UIProgressView!
    //all labels for adjusting same space
    @IBOutlet var labels: [UILabel]!

    //textfields for progress
    @IBOutlet var infoTextFields: [UITextField]! {
        didSet{
            infoProgressBar.setProgress(progress, animated: true)
        }
    }


    //progress bar code
    var progress:Float {
        if textFieldProgress(count: true) {
            return Float(infoTextFields) / Float(infoTextFields)
        } else {
            return 0
        }
    }

    //function to check if there is info in textfields
    func textFieldProgress(count: Bool) -> Bool {
        if infoTextFields?.isEmpty ?? true {
            return true
        } else {
            return false
        }
    }

}

I have all textfields linked to infoTextFields. if I the bool functions return to false the progress bar immediately completes. if I set it to false it goes from half to zero and never comes back.

Here's my view

enter image description here


Solution

  • You can use reduce to check how many fields are empty and divide by the total number of text fields:

    var progress: Float {
        return Float(infoTextFields.reduce(0) { $1.text?.isEmpty == true ? $0 : $0+1}) / Float(infoTextFields.count)
    }
    

    You will need to add a target to your text fields for editing changed control event because didSet doesn't get called when you change the text property of your text fields.

    @IBOutlet var infoTextFields: [UITextField]!
    @objc func editingChanged(_ textField: UITextField) {
        infoProgressBar.setProgress(progress, animated: true)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        infoTextFields.forEach({
            $0.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
        })
    }