The old iOS 6 switch was wider and shorter:
main.m
SwitchAppDelegate
View
SwitchAppDelegate.h
has to import
AVAudioPlayer.h
before it can mention the word
AVAudioPlayer
.
SwitchAppDelegate.h
has to declare the method
valueChanged:
so that class
View
can mention this method.
MIDI was not on the list of
supported formats,
so I converted the file
musette.mid
to MP3 with
this converter.
Then I added the resulting file
musette.mp3
Add the AVFoundation Framework to the project. (See Button for adding a framework to a project.)
The word
switch
is a keyword in Objective-C,
so I had to name the switch
mySwitch
in
View.h
.
The
UIButton
in
Button
could be set to any desired
size.
But a
UISwitch
has a preferred size,
51 × 31 pairs of pixels
(or 94 × 27 pairs of pixels in iOS 6),
which I discovered as follows.
NSLog(@"mySwitch.frame == (%g, %g), %g × %g", mySwitch.frame.origin.x, mySwitch.frame.origin.y, mySwitch.frame.size.width, mySwitch.frame.size.height );We will stay with this preferred size, even though we could change it with the
CGAffineTransformMakeScale
we saw in
Animate.
mySwitch.transform = CGAffineTransformMakeScale(.5, .5);
I don’t want to hardcode the numbers 51 × 31 into the app,
because Apple might change them in the future.
The
initWithFrame:
View
creates a switch with the default size
in the upper left corner of the
View
.
Knowing the default size,
we can then reposition the switch somewhere else,
e.g., at the center of the
View
.
As usual,
the target for the switch is designated with the method
addTarget:action:forControlEvents
valueChanged:
method of the application delegate
when the switch changes from off to on or vice versa.
2013-11-06 15:37:51.011 Switch[3555:a0b] bundle.bundlePath == "/Users/myname/Library/Application Support/iPhone Simulator/7.0.3-64/Applications/41F08B1D-1942-4E11-BC76-1694AF2319F0/Switch.app" 2013-11-06 15:37:51.013 Switch[3555:a0b] filename == "/Users/myname/Library/Application Support/iPhone Simulator/7.0.3-64/Applications/41F08B1D-1942-4E11-BC76-1694AF2319F0/Switch.app/musette.mp3" 2013-11-06 15:37:51.013 Switch[3555:a0b] url == "file:///Users/myname/Library/Application%20Support/iPhone%20Simulator/7.0.3-64/Applications/41F08B1D-1942-4E11-BC76-1694AF2319F0/Switch.app/musette.mp3" 2013-11-06 15:37:51.079 Switch[3555:a0b] player.numberOfChannels == 2 2013-11-06 15:37:52.315 Switch[3555:a0b] Application windows are expected to have a root view controller at the end of application launch 2013-11-06 15:37:54.575 Switch[3555:a0b] Playing at 0 of 25.0005 seconds. 2013-11-06 15:37:57.067 Switch[3555:a0b] Paused at 2.46821 of 25.0005 seconds. 2013-11-06 15:37:58.939 Switch[3555:a0b] Playing at 2.49465 of 25.0005 seconds. 2013-11-06 15:38:02.416 Switch[3555:a0b] Paused at 5.97166 of 25.0005 seconds. 2013-11-06 15:38:03.235 Switch[3555:a0b] Playing at 6.00093 of 25.0005 seconds. 2013-11-06 15:38:05.964 Switch[3555:a0b] Paused at 8.73048 of 25.0005 seconds. 2013-11-06 15:38:10.862 Switch[3555:a0b] Playing at 8.76408 of 25.0005 seconds. 2013-11-06 15:38:12.608 Switch[3555:a0b] Paused at 10.5101 of 25.0005 seconds.
Use the
Audio Services
in
Button
to play a short sound
(a warning,
Chinese sound effect, etc).
Use an
AVAudioPlayer
object to play a long sound
(Bach, Beethoven, Brahms).
The
application delegate is the target of the
switch
and the
delegate
of the
audio player.
The Musette in D Major (BWV Anhang 126) from the Notebook for Anna Magdalena Bach was the soundtrack for the holiday light show a few years back in Grand Central Terminal. PDF. MIDI.
player.numberOfLoops = 0;
AVAudioPlayerDelegate
protocol in the file
SwitchAppDelegate.h
.@interface SwitchAppDelegate: UIResponder <UIApplicationDelegate, AVAudioPlayerDelegate> {Now the application delegate is qualified to act as the delegate of the audio player. Insert the following statement into
application:didFinishLaunchingWithOptions:
.
//Let the application delegate be the delegate of the audio player. player.delegate = self;Add the following method to class
SwitchAppDelegate
in the file
SwitchAppDelegate.m
.- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) p successfully: (BOOL) flag { if (p == player) { [view.mySwitch setOn: NO animated: YES]; //Go back to the off position. } }You will also have to let
mySwitch
be a property of class
View
.
@property (strong, nonatomic) UISwitch *mySwitch; //in View.h
@synthesize mySwitch; //in View.m
if (![player prepareToPlay]) { NSLog(@"prepareToPlay failed"); }insert the following code. We saw the enumerator here. The format ID 778,924,083 in decimal is
2E6D7033
in hexadecimal.
The four numbers
2E
,
6D
,
70
,
33
are the
ASCII
codes of the four characters
".mp3"
.
CHAR_BIT
is the number of bits in a
char
.
Why is the sample rate a perfect square
NSEnumerator *e = [player.settings keyEnumerator]; NSString *key; while ((key = [e nextObject]) != nil) { if ([key isEqualToString: AVFormatIDKey]) { const int i = ((NSNumber *)[player.settings objectForKey: key]).intValue; NSLog(@"%@ %c%c%c%c", key, i >> 3 * CHAR_BIT & 0xFF, i >> 2 * CHAR_BIT & 0xFF, i >> 1 * CHAR_BIT & 0xFF, i >> 0 * CHAR_BIT & 0xFF ); } else { NSLog(@"%@ %@", key, [player.settings objectForKey: key]); } }
2013-11-06 16:12:53.259 Switch[3682:a0b] AVFormatIDKey .mp3 2013-11-06 16:12:53.260 Switch[3682:a0b] AVNumberOfChannelsKey 2 2013-11-06 16:12:53.263 Switch[3682:a0b] AVEncoderBitRateKey 0 2013-11-06 16:12:53.263 Switch[3682:a0b] AVSampleRateKey 44100
AVAudioPlayer
in this app and the
and the
MPMoviePlayerController
in
Video
use such totally different mechanisms to inform the rest of the app
that the media file has finished playing?