ImageView Workshop 5

In workshop 4 of the UIImageView Control tutorial, you learned how to animate images in the imageView control. Wouldn’t it be nice to play an MP3 song in the background while the images are animating. Stop it only when the user tap the view’s Stop button control? Well, to make that happen you need to add the AVFoundation.framework in the ImageViewController project so you can use properties and methods of the AVAudioPlayer class.

The AVAudioPlayer Class

An instance of the AVAudioPlayer class, called an audio player is used in your own class to play a short or long sound. It can loop a sound, play multiple sounds at the same time; it also allows control over a sound’s volume.

AVAudioPlayer Methods

Here is a partial list of properties of the AVAudioPlayer class you can use.

currentTime
This property represent the playback point, in seconds, within the timeline of the sound associated with the audio player. By setting this property you can seek to a specific point in a sound file or implement audio fast-forward and rewind functions. This property returns the playback in seconds as an NSTimeInterval (a float) value.

isPlaying
This property’s data type is a ready-only BOOL and it is for identifying whether or not the audio player is currently playing a sound. So if the audio player is playing a sound, the playing property is set to YES; otherwise, it is set to NO.

volume
This property’s data type is a float and it is used to set the audio player’s sound volume, between 0.0 and 1.0.

numberOfLoops
This property’s data type is an NSInteger (default 0) and it is used to set a sound playback frequency. Set this property a positive integer value to specify the number of times to return to the start and play the sound again. By the way, the integer value of this property is zero-index. This mean if you want to play a sound only once, you set the numberOfLoops property to 0-the default value. If you want a sound to play two times, you set the numberOfLoops property to 1, etc. Setting numberOfLoops property to a negative integer number; such as -1, will play the sound indefinitely until the audio player’s stop method is invoked.

AVAudioPlayer Methods

Here is a partial list of methods of the AVAudioPlayer class you can use.

prepareToPlay:
This method prepares the audio player for playing a sound by preloading its buffers; thus, avoiding a delay between calling the play method and the sound starting. It takes no parameters and returns a boolean (YES or NO) value.

play:
This method plays a sound. It takes no parameters and returns the boolean value YES if it is able to play a sound; otherwise, it returns NO.

stop:
This method stop playback of a sound file and doesn’t reset the currentTime property. To reset the currentTime property, set it to 0.0 after invoking the stop method. That way the next time the play method is invoked, the sound is played from the beginning.

The AVAudioPlayer class has more features, such as adjusting the audio volume or playing multiple sound at a time at different volumes. You can learn about them in Apple’s AVAudioPlayer Class Reference.

Using The AVAudioPlayer Class

Using the AVAudioPlayer class is just as easy as using any other Objective-C class; you have to do the following:

  1. Add a sound file in the project
  2. Add the AVFoundation.framework in the project
  3. Import the AVFoundation.h file
  4. Declare and initialize an instance of the AVAudioPlayer class
  5. Conform your class to the AVAudioPlayerDelegate protocol

Once you’ve done above tasks, you can user properties and methods of the AVAudioPlayer class, without the compiler complaining. Now is a good time as ever to actually use the AVAudioPlayer class to perform this workshop’s objective, which is this: Play an MP3 song in background while the images are animating. Stop it only when the user tap the view’s Stop button control.

Step1: Add a sound file in the project

The first thing I want you to do is download this song:

OnceUponATime.mp3

After unzipping the file, drag-and-drop it in the ImageViewController project.

Step 2: Add the AVFoundation.framework in the project

To add the AVFoundation.framework in the project you must do instructions shown in these numbered speech bubbles.

addframework-step1 addframework-step2

As you can see in this image, the AVFoundation.framework have been added to the project.
addframework-result

Step 3: Import the AVFoundation.h file

You need to import the AVFoundation header file so you can use the AVAudioPlayer class. Failing to import it will result in the compiler complaining when you try to use the AVAudioPlayer class. Just add this statement in the SecondViewController.h file.

#import <AVFoundation/AVFoundation.h>

Step 4: Declare & initialize an instance of the AVAudioPlayer class

Here is the code to declare an instance of the AVAudioPlayer class.

// This property variable is needed for accessing properties and methods of the AVAudioPlayer class
@property (strong, nonatomic) AVAudioPlayer *audioPlayer;

Step 5: Conform your class to the AVAudioPlayerDelegate protocol

To conform the SecondViewController class to the AVAudioPlayerDelegate protocol, you should modify the SecondViewController’s @interface line as shown below.

@interface SecondViewController : UIViewController 

Playing an MP3 Song

So far, you’ve configured the SecondViewController to use the AVAudioPlayer class. What you need to do now is declare and implement this method in the SecondViewController class. It job is to play an OnceUponATime.mp3 song you added in the project earlier on, an indefinite amount of time.

- (void)playBackgroundSound {
	// Get the sound file's name from the application bundle
	NSString *filePath = [[NSBundle mainBundle] pathForResource:@"OnceUponATime" ofType:@"mp3"];
	NSData *fileData = [NSData dataWithContentsOfFile:filePath];
	NSError *error = nil;

	// Initialize the audioPlayer property variable with the sound file
	self.audioPlayer = [[AVAudioPlayer alloc] initWithData:fileData error:&error];

	// Start playing the sound file
	[self.audioPlayer play];

	// Repeat playing the sound file indefinitely
	self.audioPlayer.numberOfLoops = -1;
}

Now, to use above method, add shaded code in the startButtonTapped method.

- (IBAction)startButtonTapped {
	if(self.imageView.isAnimating) {
		[self.imageView stopAnimating];
		[self.startButton setTitle:@"Start" forState:UIControlStateNormal];

		// Remove content from the textView control
		self.messageBox.text = nil;

		if ([self.audioPlayer isPlaying]) {
			// Stop playing the mp3 song in the background
			[self.audioPlayer stop];
		}
	} else {
		[self.imageView startAnimating];
		[self.startButton setTitle:@"Stop" forState:UIControlStateNormal];

		// Display content in the textView control
		NSString *stringUrls = [self.imagesFromServer componentsJoinedByString:@"\n"];
		self.messageBox.text = [NSString stringWithFormat:@"These %i images are animating:\n%@",
		[self.imagesFromServer count],stringUrls];

		// Play the mp3 sound in the background
		[self playBackgroundSound];
	}
}

Test The Button’s Code

Run the application. Click the second tab, then the Start button. The app work as before, only this time the OnceUponATime.mp3 song plays in the background. Let the application run for a while. When the song finish playing, it will play repeatedly. Clicking view’s Stop button stop rotating images in the image control and stop playing the song.

That’s all there is to it. Now you know how to play a song in the background while images are rotating in the imageView control.