Reputation: 477
I am creating a simple music app, and I was wondering how I can make a UiSlider to follow the progress of a audio file. Here's my project so far:
Code:
import UIKit
import AVFoundation
class SongDetailViewController: UITableViewController {
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "Song Name", ofType: "mp3")!))
audioPlayer.prepareToPlay()
var audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryPlayback)
}
}
catch {
print(error)
}
}
// Buttons
// Dismiss
@IBAction func dismiss(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
// Play
@IBAction func play(_ sender: Any) {
audioPlayer.stop()
audioPlayer.play()
}
// Pause
@IBAction func pause(_ sender: Any) {
audioPlayer.pause()
}
// Restart
@IBAction func restart(_ sender: Any) {
audioPlayer.currentTime = 0
}
}
I'm wanting to create the uislider similar to the Apple Music app where it follows the audio file's progress and whenever the user slides the ball thing (lol) it goes to that time of the song. If you could give me some code to complete this, that would be amazing!
Please keep in mind that I am fairly new to coding and am still learning swift, so keep it simple :-) Thanks again!
Upvotes: 3
Views: 3751
Reputation: 131491
Using AVAudioPlayer
you could create a periodic timer that fires several times a second (up to 60 times/second - any more would be a waste) and updates your slider based on your audio player's currentTime
property. To sync the update with screen refresh you could use a CADisplayLink
timer.
This part of my answer doesn't work:
It should also be possible to set up a Key Value Observer on your
AVAudioPlayer
scurrentTime
property so that each time the value changes your observer fires. (I haven't tried this, but it should work.)
Upvotes: 0
Reputation: 53193
If you switch to using an AVPlayer
, you can add a periodicTimeObserver
to your AVPlayer
. In the example below you'll get a callback every 1/30 second…
let player = AVPlayer(url: Bundle.main.url(forResource: "Song Name", withExtension: "mp3")!)
player.addPeriodicTimeObserver(forInterval: CMTimeMake(1, 30), queue: .main) { time in
let fraction = CMTimeGetSeconds(time) / CMTimeGetSeconds(player.currentItem!.duration)
self.slider.value = fraction
}
Where you create an audioPlayer
in your code, replace with the code above.
Upvotes: 2