patternswiftMinor
Music player in Swift
Viewed 0 times
musicplayerswift
Problem
I made a simple mp3 player that plays, pauses and stops a given song, shows the time elapsed, and has a volume control. I read the documentation and can't figure out the difference between the
pause and stop methods, although I have configured them to work as I want (i.e., pause lets you resume from where you left off while stop resets the track). import UIKit
import AVFoundation
class ViewController: UIViewController {
var player:AVAudioPlayer = AVAudioPlayer()
var musicPlaying = false
var timer:NSTimer!
@IBOutlet weak var currentTime: UILabel!
@IBOutlet weak var sliderValue: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
let audioPath = NSBundle.mainBundle().pathForResource("bach", ofType: "mp3")!
do {
try player = AVAudioPlayer(contentsOfURL: NSURL(string: audioPath)!)
} catch let error as NSError {
print(error)
}
}
@IBAction func play(sender: AnyObject) {
if musicPlaying {
player.pause()
musicPlaying = false
} else {
player.play()
musicPlaying = true
timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updateTime", userInfo: nil, repeats: true)
}
}
@IBAction func stop(sender: AnyObject) {
player.stop()
musicPlaying = false
player.currentTime = 0
}
func updateTime() {
let timePlayed = player.currentTime
let minutes = Int(timePlayed / 60)
let seconds = Int(timePlayed % 60)
currentTime.text = NSString(format:"%02d:%02d", minutes, seconds) as String
}
@IBAction func sliderChanged(sender: AnyObject) {
player.volume = sliderValue.value
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}Solution
Let's talk very generally about
There are a few relevant methods to discuss here:
Strictly speaking,
From the documentation on
Calling this method preloads buffers and acquires the audio hardware needed for playback, which minimizes the lag between calling the play method and the start of sound output.
And perhaps, the important part to read here is that calling
Calling this method, or allowing a sound to finish playing, undoes the setup performed upon calling the
So, in your specific case, where we have a view controller that does nothing but play
The
So basically, if you're not actually done with that player,
Realistically, if we want to present to the user behavior which stops the current audio from playing, and will resume the audio from the beginning of the track when play is pressed again (and we have no expectation of starting another track without some other action happening to trigger that), then we should be using
The only difference between our stop and pause buttons in this specific case should be that stop resets the current time to zero, but both buttons simply pause the player.
AVAudioPlayer.There are a few relevant methods to discuss here:
play
pause
stop
prepareToPlay
Strictly speaking,
prepareToPlay is optional, but if we call play without the player being prepared to play, there will potentially be some latency between calling play and audio actually beginning to play. If the player wasn't already prepared, the first thing that play will do is prepare it.From the documentation on
prepareToPlay:Calling this method preloads buffers and acquires the audio hardware needed for playback, which minimizes the lag between calling the play method and the start of sound output.
And perhaps, the important part to read here is that calling
stop will undo the set up. This is repeated in the documentation on stop:Calling this method, or allowing a sound to finish playing, undoes the setup performed upon calling the
play or prepareToPlay methods.So, in your specific case, where we have a view controller that does nothing but play
"bach.mp3", we should consider never actually calling stop except perhaps in viewWillDisappear. Calling stop will simply release resources that have to be re-obtained before the track can be played again. And if we continue reading the documentation for stop, we can see that the behavior of not resetting the currentTime to zero is well documented and to be expected:The
stop method does not reset the value of the currentTime property to 0. In other words, if you call stop during playback and then call play, playback resumes at the point where it left off.So basically, if you're not actually done with that player,
stop does the same as pause, but just requires a lot more work.Realistically, if we want to present to the user behavior which stops the current audio from playing, and will resume the audio from the beginning of the track when play is pressed again (and we have no expectation of starting another track without some other action happening to trigger that), then we should be using
pause and then resetting the currentTime to 0.The only difference between our stop and pause buttons in this specific case should be that stop resets the current time to zero, but both buttons simply pause the player.
Context
StackExchange Code Review Q#121310, answer score: 6
Revisions (0)
No revisions yet.