无效和重新启动后,Swift计时器将无法工作

时间:2018-05-07 10:08:22

标签: ios swift timer nstimer

我正在使用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()后,选择器将不会调用

3 个答案:

答案 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%

  • 仔细查看功能 pauseTapped(_ sender:UIButton)
  • 请参阅示例gif代码
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

如果您需要任何帮助,请告诉我

答案 2 :(得分:0)

原因是计时器开始在其他线程中执行,而不是在主线程中执行。