Segmented Controls: class UISegmentedControl

The Stop and Play buttons are initially disabled: there’s nothing to stop or play yet. See the first screenshot.

  1. When we press the Record button, the red recording light goes on and the Stop button is enabled. See the second screenshot.
  2. When we press Stop, the red light goes off, the Stop button is disabled, and the Play button is enabled.
  3. When we press Play, the Stop button is enabled and the Play button is disabled.
  4. When a playback finishes, the Stop button is disabled and the Play button is enabled.

For class AVAudioRecorder and protocol AVAudioRecorderDelegate, see this document. For class AVAudioPlayer and protocol AVAudioPlayerDelegate, see Switch. The filename suffix .caf stands for “Core Audio Format”.

On iPhone 6, the size of the UISegmentedControl defaults to (59n − 1) × 29 pairs of pixels, where n is the number of buttons. But this fact is mentioned nowhere in Apple’s documentation and may therefore change without warning.

Source code in Segmented.zip

  1. Class AppDelegate
  2. Class ViewController acts as the delegate for the audio recorder and the audio player, and as the target for the UISegmentedControl. It also sets up the audio session.
  3. Class View contains two subviews: the UISegmentedControl and a litte square UIView whose backgroundColor changes from white to red.

Create the project

The view controller imports the AVFoundation framework. The view controller also adopts two protocols: AVAudioRecorderDelegate and AVAudioPlayerDelegate.

Output from print

I recorded an audio file and listened to it twice:

inputNumberOfChannels = 2
ouputNumberOfChannels = 2
sampleRate = 44100.0
preferredSampleRate = 0.0
preferredIOBufferDuration = 0.0

path = /Users/myname/Library/Developer/CoreSimulator/Devices/01EBED35-F21B-4B4C-95BC-BFDDDC6264B4/data/Containers/Data/Application/1D186D68-B8D3-422F-9E0C-80CAB93FDE10/tmp/recording.caf

url = file:///Users/myname/Library/Developer/CoreSimulator/Devices/01EBED35-F21B-4B4C-95BC-BFDDDC6264B4/data/Containers/Data/Application/1D186D68-B8D3-422F-9E0C-80CAB93FDE10/tmp/recording.caf

audioRecorderDidFinishRecording:successfully: true
audioPlayerDidFinishPlaying:successfully: true
audioPlayerDidFinishPlaying:successfully: true

Things to try

  1. Replace the array of Strings with an array of UIImages. We saw class UIImage in America. As in that app, drag the files usa.png, canada.png, and mexico.png into the set list pane of the Images.xcassets file.

    Change the segmentedControl property of class View from

    	let segmentedControl: UISegmentedControl = UISegmentedControl(items: [
    		"Record",
    		"Stop",
    		"Play"
    	]);
    
    to the following. See Template Images.
    	let segmentedControl: UISegmentedControl = UISegmentedControl(items: [
    		UIImage(named:    "usa.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal),
    		UIImage(named: "canada.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal),
    		UIImage(named: "mexico.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal),
    	]);
    

    Each .png file is only 32 × 20 pixels, so you might want to increase the size of the UISegmentedControl by assigning to its bounds property.

  2. After creating the audio file, print its dictionary of attributes. Append the following code to the method audioRecorderDidFinishRecording.
    		if flag {	//means if flag == true
    			let fileManager: NSFileManager = NSFileManager.defaultManager();
    			var error: NSError?;
    
    			let attributes: [NSObject: AnyObject]? =
    				fileManager.attributesOfItemAtPath(url!.path!, error: &error);
    
    			if attributes != nil {
    				for (key, value) in attributes! {
    					print("\(key): \(value)");
    				}
    			}
    		}
    

    Decimal 16,777,218 is hexadecimal 1000002. Decimal 420 is octal 644, which represents the nine permission bits rw-r--r--. Anyone can read this file, but only the owner has permission to write it.

    NSFileOwnerAccountID: 502
    NSFileSystemFileNumber: 32395001
    NSFileExtensionHidden: 0
    NSFileSystemNumber: 16777218
    NSFileSize: 130372
    NSFileGroupOwnerAccountID: 20
    NSFilePosixPermissions: 420
    NSFileCreationDate: 2014-11-23 21:50:53 +0000
    NSFileType: NSFileTypeRegular
    NSFileGroupOwnerAccountName: staff
    NSFileReferenceCount: 1
    NSFileModificationDate: 2014-11-24 15:24:46 +0000
    
  3. Create a set of enumeration values which will be symbolic names for the button numbers. Define them in a separate file named Button.swift, so that they can be used in both View.swift and ViewController.swift. Select the Segmented folder in the Xcode Project Navigator.
    File → New → File…
    Choose a template for your new file:
    iOS Source, Swift File
    Next
    Save as: Button.swift
    Create

    Drag the new file Button.swift up to the other .swift files in the Project Navigator. Append the following to Button.swift.

    enum Button: Int {
    	case Record = 0;
    	case Stop;
    	case Play;
    };
    

    Change every 0 used as the second argument of setEnabled(_forSegmentAtIndex:) or as the number after a case to Button.Record.rawValue. Change every 1 to Button.Stop.rawValue. Change every 2 to Button.Play.rawValue.


  4. Add a Pause button.

  5. The border color of the red recording light is not exactly the same shade of blue as the border of the segmented control. How could we discover the r, g, b components of the color of the border of the segmented control? We could then duplicate this color using exercise 2 of Hello. Does the outline of the recording light look too much like a checkbox?