我正在使用Timer()来指示音频播放器中的当前音频位置
func startTimer() {
print("PlayerController: startTimer()")
if itemPlayTimer != nil {
return
}
itemPlayTimer = Timer.scheduledTimer(timeInterval: 0.001,
target: self,
selector: #selector(updateItemPlayerTimer),
userInfo: nil,
repeats: true)
}
@objc func updateItemPlayerTimer() {
guard let currentTime = player?.currentTime else {
return
}
updateTimeDescription?(currentTime)
}
当用户暂停播放器app无效计时器
时func stopTimer() {
itemPlayTimer?.invalidate()
itemPlayTimer = nil
}
但是再次调用startTimer()后,选择器将不会调用
答案 0 :(得分:0)
以这种方式更改您的功能:
func startTimer() {
print("PlayerController: startTimer()")
if itemPlayTimer == nil {
itemPlayTimer = Timer.scheduledTimer(timeInterval: 0.001,
target: self,
selector: #selector(updateItemPlayerTimer),
userInfo: nil,
repeats: true)
}
}
@objc func updateItemPlayerTimer() {
guard let currentTime = player?.currentTime else {
return
}
updateTimeDescription?(currentTime)
}
func stopTimer() {
if itemPlayTimer != nil {
itemPlayTimer?.invalidate()
itemPlayTimer = nil
}
}
答案 1 :(得分:0)
使用以下代码。我使用An AVPlayer 和一个示例视频来演示暂停/播放Timer。音频播放器的逻辑相同。 只需用您的audioPlayer替换AVPlayer。
这里的关键逻辑是正确管理播放/不播放的状态,并检查定时器是否等。
如此Answer
所示startTimer()只有在nil和stopTimer()停止时才会启动计时器 只有它不是零。
你只需要在之前停止计时器 创建/开始新的。
我在示例项目中实施, 100%。
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()
}
}
如果您需要任何帮助,请告诉我
答案 2 :(得分:0)
原因是计时器开始在其他线程中执行,而不是在主线程中执行。