I'm trying to create an app that is similar to SnapChat when it takes videos. You are supposed to hold down a button to start taking a video and then release it when you are done. I'm trying to implement a timeout feature after 7 seconds and also a progress bar by using a Timer
object. However, when I try fire the timer, it only calls the given selector once and that's it even though I tell it to repeat itself.
Here's my code to initialize the button:
let photoButton:UIButton = {
let but = UIButton(type: .custom)
but.layer.cornerRadius = 40
but.layer.borderColor = UIColor.white.cgColor
but.layer.borderWidth = 4
but.clipsToBounds = true
but.addTarget(self, action: #selector(takeVideo), for: .touchDown)
but.addTarget(self, action: #selector(stopVideo), for: [.touchUpInside, .touchUpOutside])
but.translatesAutoresizingMaskIntoConstraints = false
return but
}()
Here's the function takeVideo
that is called when the user starts to hold down the button. I initialize and fire the Timer
object here:
@objc func takeVideo() {
progressBar.isHidden = false
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateProgressbar), userInfo: nil, repeats: true)
startTime = Date().timeIntervalSince1970()
timer?.fire()
}
This is the function stopVideo
where I invalidate the Timer
object:
@objc func stopVideo() {
timer?.invalidate()
// stop video
}
And this is the updateProgressBar
function:
@objc private func updateProgressbar() {
let maxLength = 7.0
let difference = Date().timeIntervalSince1970 - startTime!
progressBar.progress = Float(difference / maxLength)
if difference >= maxLength {
stopVideo() // Invalidates the timer and will stop video.
}
}
It seems that this person has had a similar issue, but when I tried to incorporate his answer of presenting the current view controller using async, it still doesn't work. Here's how I present the video recording view controller:
let recorder = RecorderViewController()
recorder.db = db
DispatchQueue.main.async(execute: {
self.present(recorder, animated: true, completion: nil)
})
Edit: I've fixed the incorrectness concerning the Timer
object's fireDate
property (the fix is also fixed in the above code). It fixed my problem.