web-dev-qa-db-fra.com

Progression de la lecture audio en tant que UISlider dans Swift

J'ai vu des articles sur l'accomplissement de cela dans Objective-C mais je n'ai pas pu faire la même chose via Swift.

Plus précisément, je ne peux pas comprendre comment implémenter addPeriodicTimeObserverForInterval dans ci-dessous.

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()
    }

Toute aide serait appréciée.

17
allocate

Grâce à la suggestion de Dare ci-dessus, voici comment j'ai accompli cela:

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)

}
25
allocate

Juste pour développer mon commentaire précédent, voici comment je l'ai implémenté et cela semble fonctionner assez bien. Toutes les corrections Swift sont les bienvenues, je suis toujours un gars Obj-C pour l'instant.

@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)
}

* J'ai réglé la plage du curseur temporel entre 0 et 1 sur un storyboard

7
Dare

Plus précisément pour Swift j'ai pu le gérer comme ceci:

  1. J'ai défini la valeur maximale de scrubSlider sur la durée du fichier musical (.mp3) qui a été chargé dans cette méthode

    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. Je joueur a été réglé pour jouer la musique à l'heure définie par la valeur du scrubber.

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

La syntaxe a maintenant changé dans Swift 4:

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

Et la fonction (j'ai précédemment défini le progressSlider.maxValue sur player.duration):

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