ios Swift 中作为 UISlider 的音频播放进度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29542001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Audio playback progress as UISlider in Swift
提问by allocate
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.
任何援助将不胜感激。
回答by allocate
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)
}
回答by Dare
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 之间
回答by Delabi
Specifically for Swift I was able to handle it like this:
特别是对于 Swift,我能够像这样处理它:
I set the maximum value of the
scrubSlider
to the duration of the music file(.mp3) that was loaded in this methodoverride 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) }
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) }
我将 的最大值设置为
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) }
我的播放器被设置为在洗涤器的值设置的时间播放音乐。
@IBAction func scrub(sender: AnyObject) { player.currentTime = NSTimeInterval(scrubSlider.value) }
回答by BlackVoid
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)
}