Use the following code. I have used An AVPlayer with a sample Video to demonstrate pausing/playing with Timer. Logic is same for audio player.
Just replace AVPlayer with your audioPlayer.
Key logic here is to properly manage the state of Playing/not playing and checking timer for nil etc.
As indicated in this Answer
startTimer() starts the timer only if it's nil and stopTimer() stops
it only if it's not nil.
You have only to take care of stopping the timer before
creating/starting a new one.
I have implemented this in a sample project and is working 100%.
- Carefully See the function pauseTapped(_ sender: UIButton)
- See sample gif At end of Code
import UIKit
import AVKit
class TimerVC: UIViewController {
///A container view for displaying the AVPlayer.
@IBOutlet weak var playerView: UIView!
/// A button to play and pause the video
@IBOutlet weak var btnPause: UIButton!
///to maintain the status of AVPlayer playing or not
var flagPlaying = true
///An AVPlayer for displaying and playing the video
var player: AVPlayer?
///to show the current time to user
@IBOutlet weak var lblCurrentTime: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//add an AVPlayer with sample URL link
addVideoPlayer( playerView: playerView)
}
///Timer
var itemPlayTimer: Timer?
@objc func startTimer() {
if itemPlayTimer != nil {
return
}
itemPlayTimer = Timer.scheduledTimer(timeInterval: 0.001,
target: self,
selector: #selector(updateItemPlayerTimer),
userInfo: nil,
repeats: true)
}
///update time label
@objc func updateItemPlayerTimer() {
guard let currentTime = player?.currentTime else {
return
}
updateTimeDescription(currentTime())
}
func updateTimeDescription( _ currentTime :CMTime ) {
self.lblCurrentTime.text = "\(currentTime.seconds)"
}
///To Pause and play the video
@IBAction func pauseTapped(_ sender: UIButton) {
if flagPlaying {
//pause
if itemPlayTimer != nil {
player?.pause()
itemPlayTimer?.invalidate()
itemPlayTimer = nil
flagPlaying = false
DispatchQueue.main.async {
self.btnPause.setTitle("Play", for: .normal)
}
}
}else {
//not playing
if itemPlayTimer == nil {
player?.play()
startTimer()
flagPlaying = true
DispatchQueue.main.async {
self.btnPause.setTitle("Pause", for: .normal)
}
}
}
}
private func addVideoPlayer(playerView: UIView) {
//let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer.init(url: URL.init(string: "http://techslides.com/demos/sample-videos/small.mp4")!)
let layer: AVPlayerLayer = AVPlayerLayer(player: player)
layer.backgroundColor = UIColor.white.cgColor
layer.frame = CGRect(x: 0, y: 0, width: playerView.frame.width, height: playerView.frame.height)
layer.videoGravity = AVLayerVideoGravity.resizeAspectFill
playerView.layer.sublayers?.forEach({$0.removeFromSuperlayer()})
playerView.layer.addSublayer(layer)
flagPlaying = true
player?.play()
startTimer()
}
}
Working Example

Let me know if you need any help