简体   繁体   English

音频播放在Swift中作为UISlider进行

[英]Audio playback progress as UISlider in Swift

I've seen some posts about accomplishing this in Objective-C but I've been unable to do the same via Swift. 我已经看过一些关于在Objective-C中实现这一点的帖子,但我无法通过Swift做同样的事情。

Specifically, I can't figure out how to implement addPeriodicTimeObserverForInterval in the below. 具体来说,我无法弄清楚如何在下面实现addPeriodicTimeObserverForInterval

var player : AVAudioPlayer! = nil

@IBAction func playAudio(sender: AnyObject) {
    playButton.selected = !(playButton.selected)
    if playButton.selected {
        let fileURL = NSURL(string: toPass)
        player = AVAudioPlayer(contentsOfURL: fileURL, error: nil)
        player.numberOfLoops = -1 // play indefinitely
        player.prepareToPlay()
        player.delegate = self
        player.play()
        startTime.text = "\(player.currentTime)"
        endTime.text = NSString(format: "%.1f", player.duration)
    } else {
        player.stop()
    }

Any assistance would be appreciated. 任何援助将不胜感激。

Thanks to the suggestion of Dare above, here's how I accomplished this: 感谢Dare的建议,以下是我如何完成这项工作:

var updater : CADisplayLink! = nil

@IBAction func playAudio(sender: AnyObject) {
    playButton.selected = !(playButton.selected)
    if playButton.selected {
        updater = CADisplayLink(target: self, selector: Selector("trackAudio"))
        updater.frameInterval = 1
        updater.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
        let fileURL = NSURL(string: toPass)
        player = AVAudioPlayer(contentsOfURL: fileURL, error: nil)
        player.numberOfLoops = -1 // play indefinitely
        player.prepareToPlay()
        player.delegate = self
        player.play()
        startTime.text = "\(player.currentTime)"
        theProgressBar.minimumValue = 0
        theProgressBar.maximumValue = 100 // Percentage
    } else {
        player.stop()
    }
}

func trackAudio() {
    var normalizedTime = Float(player.currentTime * 100.0 / player.duration)
    theProgressBar.value = normalizedTime
}

@IBAction func cancelClicked(sender: AnyObject) {
    player.stop()
    updater.invalidate()
    dismissViewControllerAnimated(true, completion: nil)

}

Just to elaborate on my previous comment, this is how I implemented it and it seems to work pretty well. 只是详细说明我以前的评论,这就是我实现它的方式,它看起来效果很好。 Any Swift corrections are more than welcome, I'm still an Obj-C guy for now. 任何Swift更正都非常受欢迎,我现在仍然是Obj-C的家伙。

@IBAction func playAudio(sender: AnyObject) {

    var playing = false

    if let currentPlayer = player {
        playing = player.playing;
    }else{
        return;
    }

    if !playing {
        let filePath = NSBundle.mainBundle().pathForResource("3e6129f2-8d6d-4cf4-a5ec-1b51b6c8e18b", ofType: "wav")
        if let path = filePath{
            let fileURL = NSURL(string: path)
            player = AVAudioPlayer(contentsOfURL: fileURL, error: nil)
            player.numberOfLoops = -1 // play indefinitely
            player.prepareToPlay()
            player.delegate = self
            player.play()

            displayLink = CADisplayLink(target: self, selector: ("updateSliderProgress"))
            displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode!)
        }

    } else {
        player.stop()
        displayLink.invalidate()
    }
}

func updateSliderProgress(){
    var progress = player.currentTime / player.duration
    timeSlider.setValue(Float(progress), animated: false)
}

*I set time slider's range between 0 and 1 on a storyboard *我在故事板上设置时间滑块的范围在0到1之间

Specifically for Swift I was able to handle it like this: 特别是对于Swift,我能够像这样处理它:

  1. I set the maximum value of the scrubSlider to the duration of the music file(.mp3) that was loaded in this method 我将scrubSlider的最大值设置为此方法中加载的音乐文件(.mp3)的持续时间

     override func viewDidLoad() { super.viewDidLoad() do { try player = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("bach", ofType: "mp3")!)) scrubSlider.maximumValue = Float(player.duration) } catch { //Error } _ = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(ViewController.updateScrubSlider), userInfo: nil, repeats: true) } 
  2. I player was set to play the music at the time set by the value of the scrubber. 我的播放器设置为在洗涤器的值设置的时间播放音乐。

     @IBAction func scrub(sender: AnyObject) { player.currentTime = NSTimeInterval(scrubSlider.value) } 

Syntax has now changed in Swift 4: Swift 4中的语法现在已经改变了:

updater = CADisplayLink(target: self, selector: #selector(self.trackAudio))
updater.preferredFramesPerSecond = 1
updater.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)

And the function (I have previously set the progressSlider.maxValue to player.duration): 和函数(我之前已将progressSlider.maxValue设置为player.duration):

@objc func trackAudio() {
    progressSlider.value = Float(player!.currentTime)
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM