Reputation: 13
I have a pulsing rectangle animated with animateWithDuration and setAnimationRepeatCount()
.
I'm trying to add a sound effect in the animations block witch is "clicking" synchronously. But the sound effect is only playing once. I can't find any hint on this anywhere.
UIView.animateWithDuration(0.5,
delay: 0,
options: UIViewAnimationOptions.AllowUserInteraction | UIViewAnimationOptions.CurveEaseOut | UIViewAnimationOptions.Repeat,
animations: {
UIView.setAnimationRepeatCount(4)
self.audioPlayer.play()
self.img_MotronomLight.alpha = 0.1
}, completion: nil)
The sound effect should play four times but doesn't.
Audio Implementation:
//global:
var metronomClickSample = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("metronomeClick", ofType: "mp3")!)
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
audioPlayer = AVAudioPlayer(contentsOfURL: metronomClickSample, error: nil)
audioPlayer.prepareToPlay()
....
}
@IBAction func act_toggleStartTapped(sender: AnyObject) {
....
UIView.animateWithDuration(....
animations: {
UIView.setAnimationRepeatCount(4)
self.audioPlayer.play()
self.img_MotronomLight.alpha = 0.1
}, completion: nil)
}
Upvotes: 1
Views: 840
Reputation: 5566
Providing the UIViewAnimationOptions.Repeat
option does NOT cause the animation block to be called repeatedly. The animation is repeated on a CoreAnimation
level. If you place a breakpoint in the animation block, you'll notice that it is only executed once.
If you want the animation to execute in a loop alongside the sound, create a repeating NSTimer
and call the animation / sound from there. Keep in mind that the timer will retain the target, so don't forget to invalidate the timer to prevent retain cycle.
EDIT: Added implementation below
First, we'll need to create the timer, assuming we have an instance variable called timer
. This can be done in viewDidLoad:
or init
method of a view. Once initialized, we schedule for execution with the run loop, otherwise it will not fire repeatedly.
self.timesFired = 0
self.timer = NSTimer(timeInterval: 0.5, target: self, selector:"timerDidFire:", userInfo: nil, repeats: true)
if let timer = self.timer {
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode)
}
The following is the method fired by the timer every interval (in this case 0.5 seconds). Here, you can run your animations and audio playback. Note that UIViewAnimationOptions.Repeat
option has been removed since the timer is now responsible for handling the repeating animation and audio. If you only the timer to fire a specific number of times, you can add an instance variable to keep track of times fired and invalidate the timer if the count is above the threshold.
func timerDidFire(timer: NSTimer) {
/*
* If limited number of repeats is required
* and assuming there's an instance variable
* called `timesFired`
*/
if self.timesFired > 5 {
if let timer = self.timer {
timer.invalidate()
}
self.timer = nil
return
}
++self.timesFired
self.audioPlayer.play()
var options = UIViewAnimationOptions.AllowUserInteraction | UIViewAnimationOptions.CurveEaseOut;
UIView.animateWithDuration(0.5, delay: 0, options: options, animations: {
self.img_MotronomLight.alpha = 0.1
}, completion: nil)
}
Upvotes: 2
Reputation: 198
Without seeing the implementation of the audio player some things I can think of include:
The audio file is too long and perhaps has silence on the end of it so it is not playing the first part of the file which has the sound in it
the audio file needs to be set to the beginning of the file every time (it could just be playing the end of the file the other 3 times leading to no audio output)
The animation is happening to quickly and the audio doesn't have time to buffer
Hopefully these suggestions help you narrow down the problem but without seeing the implementation of the player, it is really hard to say what the actual problem is.
Upvotes: 0