Swift Progress View with NSTimer

japes Sophey picture japes Sophey · Mar 9, 2016 · Viewed 13.9k times · Source

I have a Progress view bar that I would like to use to indicate time. This is my first project in Swift, and I am unsure how to go about this. So any help/ advise would be appreciated ...

(Using Xcode 7.2 and Swift 2.0)

Below Is my view controller. When 'btnPlaySession' is triggered, the content on the view controller is changed every 20 seconds. While the timer is counting to 20, id like to indicate this with the progress bar (so the progress bar resets, each time the content changes).

class CreatedSessionViewController: UIViewController {

var createdSession: [YogaPose]!
var poseDuration: Double = 20.00 
var timer = NSTimer!()
var currentPoseIndex = 1

//Outlets:
@IBOutlet var poseProgressView: UIProgressView!
@IBOutlet var lblPoseCount: UILabel!
@IBOutlet var lblPoseName: UILabel!
@IBOutlet var imgPose: UIImageView!
@IBOutlet var tvDescription: UITextView!

// Do any additional setup after loading the view:
override func viewDidLoad() {
    super.viewDidLoad()

    displayFirstPoseInArray()
}

func displayFirstPoseInArray(){
    lblPoseCount.text = (String(currentPoseIndex) + "/" + String(createdSession.count))
    lblPoseName.text = createdSession[0].title
    imgPose.image = UIImage(named: String(format: "%d.jpg", (createdSession[0].id)!))
    tvDescription.text = createdSession[0].desc
}

@IBAction func btnPlaySession(sender: AnyObject) {
    timer = NSTimer.scheduledTimerWithTimeInterval(poseDuration, target: self, selector: "getNextPoseData", userInfo: nil, repeats: true)
}

func getNextPoseData(){
    if (currentPoseIndex < createdSession.count){

        setProgressBar()

        lblPoseCount.text = (String(currentPoseIndex + 1) + "/" + String(createdSession.count))
        lblPoseName.text = createdSession[currentPoseIndex].title
        imgPose.image = UIImage(named: String(format: "%d.jpg",(createdSession[currentPoseIndex].id)!))
        tvDescription.text = createdSession[currentPoseIndex].desc
        currentPoseIndex += 1
        print(currentPoseIndex)
    }
}

func setProgressBar(){


}
}

Answer

Russell picture Russell · Mar 9, 2016

OK - so if you want the progress bar to update every second, then you need a timer that fires every second - but which does it 20 times, and calls setProgressBar as selector instead of getNextPoseData

within setProgressBar, you need to increment a class-level attribute, indexProgressBar perhaps, and simply set the progress bar attribute progress to 1.0 / indexProgressBar

if indexProgressBar == 20, then call getNextPoseData, and reset your progress bar

and here's a simplified version of how you might do that

class ViewController: UIViewController
{
    @IBOutlet weak var progressBar: UIProgressView!
    var timer = NSTimer!()
    var poseDuration = 20
    var indexProgressBar = 0
    var currentPoseIndex = 0

    override func viewDidLoad()
    {
        super.viewDidLoad()

        // initialise the display
        progressBar.progress = 0.0
    }


    @IBAction func cmdGo(sender: AnyObject)
    {
        // display the first pose
        getNextPoseData()

        // start the timer
        timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "setProgressBar", userInfo: nil, repeats: true)
    }

    func getNextPoseData()
    {
        // do next pose stuff
        currentPoseIndex += 1
        print(currentPoseIndex)
    }

    func setProgressBar()
    {
        if indexProgressBar == poseDuration
        {
            getNextPoseData()

            // reset the progress counter
            indexProgressBar = 0
        }

        // update the display
        // use poseDuration - 1 so that you display 20 steps of the the progress bar, from 0...19
        progressBar.progress = Float(indexProgressBar) / Float(poseDuration - 1)

        // increment the counter
        indexProgressBar += 1
    }
}