====Welcome==== Over the winter break I've deluged various Objective-C and IOS programming concepts into my free time. For this introductory project I'll be expanding on the "power hour" drinking game concept I explored using C earlier in December. **//For this example 6 seconds with represent one whole minute//** This can be changed by updating the delay time on the //performSelector// methods to the appropriate time. ====Components==== The following components are what make up the basic structure of the app. The rest is handled autonomously by Apple's built in frameworks. - PowerHourAppDelegate.h - Define main class, interface, window, and lower view controller. - PowerHourAppDelegate.m - Implementation of header delegate. - PowerHourViewController.h - Global user interface labels, actions, and classes. - PowerHourViewController.m - implementation of main functions and logic. - PowerHourViewController.xib - Graphical interface builder file ====Contents of Components==== PowerHourAppDelegate.h #import @class PowerHourViewController; @interface PowerHourAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) PowerHourViewController *viewController; @end PowerHourAppDelegate.m #import "PowerHourAppDelegate.h" #import "PowerHourViewController.h" @implementation PowerHourAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.viewController = [[PowerHourViewController alloc] initWithNibName:@"PowerHourViewController" bundle:nil]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end PowerHourViewController.h #import @interface PowerHourViewController : UIViewController { IBOutlet UILabel *minuteLabel; IBOutlet UILabel *drinkLabel; } - (IBAction)startHour:(id)sender; @end @interface MyClass : NSObject @end PowerHourViewController.m #import "PowerHourViewController.h" @interface PowerHourViewController () @end @implementation PowerHourViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 0) { NSLog(@"user pressed no"); start.hidden = NO; } else { NSLog(@"user pressed yes"); static dispatch_once_t oneceToken; dispatch_once(&oneceToken, ^{ [self myTimerTick]; }); } } - (void) startHour: (id) sender{ start.hidden = YES; UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Ready?" message:@"Are you sure?" delegate:self cancelButtonTitle:@"no" otherButtonTitles:@"yes", nil]; [alertView show]; [alertView release]; } - (void) resetHour{ [self myTimerTick]; } -(void) myTimerTick { static int count = 0; static int meta = 0; NSString *complete = @"All done!"; static dispatch_once_t oneceToken; dispatch_once(&oneceToken, ^{ [self initialText]; }); NSLog(@"minute: #%d\n", count); NSLog(@"meta: #%d\n", meta); NSString *theLabel = [NSString stringWithFormat:@"Minute #%d", count]; minuteLabel.text = theLabel; if (count < 61) { count++; [self performSelector:@selector(metaKill) withObject:nil afterDelay:1]; [self performSelector:@selector(myTimerTick) withObject:nil afterDelay:6]; } if (meta < 60) { meta++; [self performSelector:@selector(ready) withObject:nil afterDelay:5]; [self performSelector:@selector(drink) withObject:nil afterDelay:6]; } else { UIAlertView: minuteLabel.text = complete; drinkLabel.text = nil; } } - (void) drink { NSString *drink = @"Drink!"; drinkLabel.text = drink; } - (void) ready { NSString *ready = @"Get Ready..."; drinkLabel.text = ready; } - (void) initialText { NSString *initialLabel =@"Minute #1"; NSString *ready = @"Take your first drink"; minuteLabel.text = initialLabel; drinkLabel.text = ready; } - (void) metaKill { drinkLabel.text = nil; } @end PowerHourViewController.xib {{:user:asowers:xib_file.png?300|}} In use: {{:user:asowers:ready.png?300|}} Running with output: {{:user:asowers:running.png?300|}} ====2/2/13 Update==== The app has been renamed as "Minute Shuffle" because Apple's full of nazis. There is now a second class that calls Apple's music player view. This initializes the music player and runs on separate thread. The user then returns to the "game" in the first class while the other thread handles music. The main thread can make calls to the music thread to skip, rewind, pause, and play music. Here's the code output with photos of the program running. ====code==== minuteShuffleViewController.h // // minuteShuffleViewController.h // MinuteShuffle // // Created by Andrew Sowers on 1/21/13. // Copyright (c) 2013 Andrew Sowers. All rights reserved. // #import #import #import #import @interface minuteShuffleViewController : UIViewController{ __weak IBOutlet UIToolbar *bar; __weak IBOutlet UILabel *minuteLabel; __weak IBOutlet UILabel *drinkLabel; __weak IBOutlet UIButton *start; __weak IBOutlet UIButton *showInfo; __weak IBOutlet UIButton *hideInfo; __weak IBOutlet UIBarButtonItem *restart; __weak IBOutlet UIBarButtonItem *stop; __weak IBOutlet UIBarButtonItem *resume; __weak IBOutlet UIProgressView * threadProgressView; __weak IBOutlet UILabel *timeLabel; __weak IBOutlet UITextView *info; __weak IBOutlet UILabel *minutesLeft; __weak IBOutlet UIBarButtonItem *musicButton; __weak IBOutlet UIImageView *artworkImageView; __weak IBOutlet UIButton *bigGetMusic; NSString *theTime; NSString *timeLeft; SystemSoundID shot; UIBackgroundTaskIdentifier bgTask; UIApplication *app; CFURLRef soundURL; } @property (nonatomic, retain) NSTimer *progTime; @property (nonatomic, retain) MPMusicPlayerController *musicPlayer; - (IBAction)hideInfo:(id)sender; - (IBAction)hideShowInfo:(id)sender; - (IBAction)startHour:(id)sender; - (IBAction)stopHour:(id)sender; - (IBAction)restartHour:(id)sender; - (IBAction)resume:(id)sender; - (IBAction)nextSong:(id)sender; - (IBAction)bigGetMusic:(id)sender; @end @interface startClass : NSObject @end @interface restartClass : NSObject @end @interface stopClass : NSObject @end minuteShuffleViewController.m // // minuteShuffleViewController.m // MinuteShuffle // // Created by Andrew Sowers on 1/21/13. // Copyright (c) 2013 Andrew Sowers. All rights reserved. // #import "minuteShuffleViewController.h" static int stateCheck; static int stateCheckTwo; float progress; int minutesLeftInt; int minuteLeftToString; int loopCount; int stopValue; int labelCountTimeInner; int labelCountTimeOuter; int tag; int minute; int second; int miliSec; int minuteStopValue; int secondStopValue; @interface minuteShuffleViewController () @end @implementation minuteShuffleViewController @synthesize musicPlayer; - (void)viewDidLoad { [super viewDidLoad]; [self initialChecker]; [self viewInitialzationStuff]; musicPlayer = [MPMusicPlayerController iPodMusicPlayer]; if (second >= 1) { [self artCheck]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (void)viewWillDisappear:(BOOL)animated { if (stateCheckTwo == 1){ [self stopLeaveViewFunc]; [self artCheck]; NSLog(@"state check two is %d", stateCheckTwo); } if (stateCheckTwo == 2){ [self stopFunc]; NSLog(@"state check two is %d", stateCheckTwo); } if (stateCheckTwo == 3) { [self initialLoader]; NSLog(@"state check two is %d", stateCheckTwo); } } - (id) init { [self myTimerTick]; loopCount = stopValue; labelCountTimeOuter = stopValue; return self; } - (void)viewInitialzationStuff{ } - (void)initialChecker { if (stateCheck == 0){ [self initialLoader]; } if (stateCheck == 1) { [self viewDidLoad]; } if (stateCheck == 2) { if (stateCheckTwo == 2){ [self resumeViewWithoutTimer]; } if (stateCheckTwo == 1){ [self resumeFunc]; } [self timeLabelLogic]; timeLeft = [NSString stringWithFormat:@"Minutes Left: %d", minuteLeftToString]; minutesLeft.text = timeLeft; NSString *theLabel = [NSString stringWithFormat:@"Minute #%d progress", loopCount]; minuteLabel.text = theLabel; threadProgressView.progress = progress; } if (stateCheckTwo == 3) { [self initialLoader]; NSLog(@"stateTHREE FIRES"); } } - (void) initialLoader { [threadProgressView setProgress:0.00]; progress = 0.0; labelCountTimeInner = -1; minute = 0; second = -1; minutesLeftInt = 60; minutesLeft.hidden = YES; info.hidden = YES; hideInfo.hidden = YES; showInfo.hidden = YES; minuteLabel.hidden = YES; drinkLabel.hidden = YES; bar.hidden = YES; stop.enabled = NO; restart.enabled = NO; resume.enabled = NO; threadProgressView.hidden = YES; timeLabel.hidden = YES; soundURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("Shot"), CFSTR("aiff"), NULL); AudioServicesCreateSystemSoundID(soundURL, &shot); app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; }]; [musicPlayer stop]; NSLog(@"initLOADS"); } - (void) alertView :(UIAlertView *) alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 0) { NSLog(@"user pressed (start)no"); start.hidden = NO; if (alertView.tag == 99) { [alertView setTag:0]; start.hidden = NO; bigGetMusic.hidden = NO; } if (alertView.tag == 98) { [alertView setTag:0]; start.hidden = YES; } if (alertView.tag == 97) { start.hidden = YES; [alertView setTag:0]; } } if (alertView.tag == 99) { NSLog(@"user pressed (start)yes"); [self startFunc]; tag = alertView.tag; } if (alertView.tag == 98) { [self restartFunc]; tag = alertView.tag; } if (alertView.tag == 97) { [self stopFunc]; stop.enabled = NO; resume.enabled = YES; tag = alertView.tag; } } - (void) startFunc { [self myTimerTick]; start.hidden = YES; stop.enabled = YES; bigGetMusic.hidden = YES; restart.enabled = YES; drinkLabel.hidden = NO; minuteLabel.hidden = NO; showInfo.hidden = NO; minutesLeft.hidden = NO; AudioServicesPlayAlertSound(shot); [self doStuff]; minuteLeftToString = minutesLeftInt - minute; timeLeft = [NSString stringWithFormat:@"Minutes Left: %d", minuteLeftToString]; minutesLeft.text = timeLeft; stateCheck = 1; stateCheckTwo = 1; } - (void) stopFunc { [self.progTime invalidate]; self.progTime = nil; stopValue = loopCount; //NSLog(@"The Stop Value is %d", stopValue); //NSLog(@"user pressed (stop)YES"); start.hidden = YES; bigGetMusic.hidden = YES; stateCheck = 2; stateCheckTwo = 2; [musicPlayer pause];} - (void) stopLeaveViewFunc { [self.progTime invalidate]; self.progTime = nil; stopValue = loopCount; //NSLog(@"The Stop Value is %d", stopValue); //NSLog(@"user pressed (stop)YES"); start.hidden = YES; bigGetMusic.hidden = YES; stateCheck = 2; stateCheckTwo = 1; } - (void) restartFunc { loopCount = 0; [threadProgressView setProgress:0.00]; [self.progTime invalidate]; self.progTime = nil; [self initialLoader]; labelCountTimeOuter = 0; labelCountTimeInner = 0; app = nil; bgTask = 0; start.hidden = NO; restart.enabled = YES; stop.enabled = YES; minutesLeft.hidden = YES; artworkImageView.hidden = YES; bigGetMusic.hidden = NO; stateCheck = 2; stateCheckTwo = 3; } - (void) resume:(id)sender { [self resumeFunc]; [self artCheck]; } - (void) resumeFunc { [self myTimerTick]; info.hidden = YES; start.hidden = YES; bigGetMusic.hidden = YES; stop.enabled = YES; restart.enabled = YES; resume.enabled = NO; threadProgressView.hidden = NO; //NSLog(@"resume func"); stateCheckTwo = 1; artworkImageView.hidden = NO; [musicPlayer play]; } - (void) resumeViewWithoutTimer { info.hidden = YES; start.hidden = YES; bigGetMusic.hidden = YES; stop.enabled = NO; restart.enabled = YES; resume.enabled = YES; threadProgressView.hidden = NO; //NSLog(@"resume func without timer"); } - (void) hideShowInfo:(id)sender { hideInfo.hidden = NO; showInfo.hidden = YES; info.hidden = NO; } - (void) hideInfo:(id)sender { hideInfo.hidden = YES; showInfo.hidden = NO; info.hidden = YES; } - (void) startHour: (id) sender{ UIAlertView* startClass = [[UIAlertView alloc] initWithTitle:@"Ready to play?" message:@"You may want to select music if it's not already playing" delegate:self cancelButtonTitle:@"Not ready yet" otherButtonTitles:@"Music's playing", nil]; startClass.tag = 99; [startClass show]; start.hidden = YES; bigGetMusic.hidden = YES; } - (void) restartHour: (id) sender{ UIAlertView* restartClass = [[UIAlertView alloc] initWithTitle:@"Restart?" message:@"" delegate:self cancelButtonTitle:@"no" otherButtonTitles:@"yes", nil]; restartClass.tag = 98; [restartClass show]; } - (void) stopHour:(id)sender{ UIAlertView* stopClass = [[UIAlertView alloc] initWithTitle:@"Pause?" message:@"" delegate:self cancelButtonTitle:@"no" otherButtonTitles:@"yes", nil]; stopClass.tag = 97; [stopClass show]; } - (void) myTimerTick { bar.hidden = NO; self.progTime = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(doStuff) userInfo:nil repeats:YES]; } - (void)doStuff { NSString *complete = @"All Done!"; if (loopCount >= 60) { threadProgressView.hidden = YES; minutesLeft.text = complete; drinkLabel.hidden = YES; [_progTime invalidate]; _progTime = nil; threadProgressView.hidden = YES; timeLabel.hidden = YES; bar.hidden = NO; stop.enabled = NO; bgTask = 0; [self.progTime invalidate]; self.progTime = nil; minuteLabel.hidden = YES; [musicPlayer stop]; } else { [self labelCount]; [self doing]; [self artCheck]; if ([musicPlayer playbackState] == MPMusicPlaybackStatePaused) { [musicPlayer play]; } NSString *theLabel = [NSString stringWithFormat:@"Minute #%d progress", loopCount]; minuteLabel.text = theLabel; } } - (void) artCheck { artworkImageView.hidden = NO; MPMediaItem *currentItem = [musicPlayer nowPlayingItem]; UIImage *artworkImage = [UIImage imageNamed:@"noArtworkImage.png"]; MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork]; artworkImage = [artwork imageWithSize: CGSizeMake (300, 300)]; [artworkImageView setImage:artworkImage]; } - (void) doing { threadProgressView.hidden = NO; bar.hidden = NO; progress = progress + ((float)1/(float)60); threadProgressView.progress = progress; } - (void) labelCount { timeLabel.hidden = NO; if (second <= 58) { ++second; } else { theTime = [NSString stringWithFormat:(@"%d:00"), minute]; timeLabel.text = theTime; second = 0; loopCount++; minute++; labelCountTimeInner = 0; labelCountTimeOuter++; //NSLog(@"ProgressViewINNER: %f", progress); //NSLog(@"LoopCount: %d", loopCount); progress = 0.0; bgTask = 0; [self performSelectorOnMainThread:@selector(nextSong) withObject:nil waitUntilDone: NO]; [self.progTime invalidate]; self.progTime = nil; [self myTimerTick]; [self bgMetaReset]; [musicPlayer shuffleMode]; } if (labelCountTimeInner == 0) { [self minuteLeftFunc]; } ++labelCountTimeInner; while (second == 10) { [self metaKill]; break; } [self timeLabelLogic]; //NSLog(@"labelCountTime is %d", labelCountTimeInner); } - (void) timeLabelLogic { if (minute <= 9){ if (second <= 9) { theTime = [NSString stringWithFormat:(@"0%d:0%d"), minute, second]; timeLabel.text = theTime; } else { theTime = [NSString stringWithFormat:(@"0%d:%d"), minute, second]; timeLabel.text = theTime; theTime = [NSString stringWithFormat:(@"0%d:%d"), minute, second]; timeLabel.text = theTime; } } if (minute >= 10) { if (second <= 9) { theTime = [NSString stringWithFormat:(@"%d:0%d"), minute, second]; timeLabel.text = theTime; } else { theTime = [NSString stringWithFormat:(@"%d:%d"), minute, second]; timeLabel.text = theTime; } } if (loopCount == 0 && second <= 9) { [self initialText]; } if (second >= 50 && second <= 60){ [self ready]; } if (loopCount >= 1 && second >= 0 && second <= 10){ [self drink]; } if (second >= 10 && second < 50) { [self metaKill]; } } - (void) nextSong { AudioServicesPlayAlertSound(shot); [musicPlayer shuffleMode]; [musicPlayer skipToNextItem]; } - (void) minuteLeftFunc { if (minute <= 60) { minuteLeftToString = minutesLeftInt - minute; timeLeft = [NSString stringWithFormat:@"Minutes Left: %d", minuteLeftToString]; minutesLeft.text = timeLeft; } } - (void)bgMetaReset { soundURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("Shot"), CFSTR("aiff"), NULL); AudioServicesCreateSystemSoundID(soundURL, &shot); app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; }]; } - (void) nextSong:(id)sender { [self skipSong]; } - (void) skipSong { [musicPlayer skipToNextItem]; } - (void) bigGetMusic:(id)sender { bigGetMusic.hidden = YES; [_progTime invalidate]; _progTime = nil; } - (void) otherViewStateChanger{ stateCheckTwo = 2; } - (void) drink { NSString *drink = @"Skip!"; drinkLabel.text = drink; } - (void) ready { NSString *ready = @"Get Ready..."; drinkLabel.text = ready; } - (void) initialText { NSString *ready = @"Start!"; drinkLabel.text = ready; } - (void) metaKill { drinkLabel.text = nil; } @end musicViewController.h #import #import #import #import @interface musicViewController: UIViewController { MPMusicPlayerController *musicPlayer; IBOutlet UIImageView *artworkImageView; IBOutlet UILabel *titleLabel; IBOutlet UILabel *artistLabel; IBOutlet UILabel *albumLabel; IBOutlet UISlider *volumeSlider; IBOutlet UIBarButtonItem *playPauseButton; } - (IBAction)showMediaPicker:(id)sender; - (IBAction)volumeChanged:(id)sender; - (IBAction)previousSong:(id)sender; - (IBAction)playPause:(id)sender; - (IBAction)nextSong:(id)sender; - (void) registerMediaPlayerNotifications; @property (nonatomic, retain) MPMusicPlayerController *musicPlayer; @end musicViewController.m #import "musicViewController.h" @interface musicViewController () @end @implementation musicViewController @synthesize musicPlayer; - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; musicPlayer = [MPMusicPlayerController iPodMusicPlayer]; [volumeSlider setValue:[musicPlayer volume]]; if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) { //playPauseButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:@selector(registerMediaPlayerNotifications)]; //playPauseButton.style = UIBarButtonSystemItemPlay; //self.navigationItem.rightBarButtonItem = playPauseButton; [playPauseButton setStyle:(UIBarButtonSystemItemPause)]; } else { playPauseButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPause target:self action:@selector(registerMediaPlayerNotifications)]; //playPauseButton.style = UIBarButtonSystemItemPause; [playPauseButton setStyle:(UIBarButtonSystemItemPlay)]; } [self registerMediaPlayerNotifications]; [self handle_NowPlayingItemChanged:(id) self]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } - (void) viewDidDisappear:(BOOL)animated{ } #pragma mark - Notifications - (void) registerMediaPlayerNotifications { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver: self selector: @selector (handle_NowPlayingItemChanged:) name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification object: musicPlayer]; [notificationCenter addObserver: self selector: @selector (handle_PlaybackStateChanged:) name: MPMusicPlayerControllerPlaybackStateDidChangeNotification object: musicPlayer]; [notificationCenter addObserver: self selector: @selector (handle_VolumeChanged:) name: MPMusicPlayerControllerVolumeDidChangeNotification object: musicPlayer]; [musicPlayer beginGeneratingPlaybackNotifications]; } - (void) handle_NowPlayingItemChanged: (id) notification { MPMediaItem *currentItem = [musicPlayer nowPlayingItem]; UIImage *artworkImage = [UIImage imageNamed:@"noArtworkImage.png"]; MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork]; artworkImage = [artwork imageWithSize: CGSizeMake (300, 300)]; [artworkImageView setImage:artworkImage]; NSString *titleString = [currentItem valueForProperty:MPMediaItemPropertyTitle]; if (titleString) { titleLabel.text = [NSString stringWithFormat:@"Title: %@",titleString]; } else { titleLabel.text = @""; } NSString *artistString = [currentItem valueForProperty:MPMediaItemPropertyArtist]; if (artistString) { artistLabel.text = [NSString stringWithFormat:@"Artist: %@",artistString]; } else { artistLabel.text = @""; } NSString *albumString = [currentItem valueForProperty:MPMediaItemPropertyAlbumTitle]; if (albumString) { albumLabel.text = [NSString stringWithFormat:@"Album: %@",albumString]; } else { albumLabel.text = @""; } } - (void) handle_PlaybackStateChanged: (id) notification { MPMusicPlaybackState playbackState = [musicPlayer playbackState]; if (playbackState == MPMusicPlaybackStatePaused) { [playPauseButton setStyle:(UIBarButtonSystemItemPlay)]; } else if (playbackState == MPMusicPlaybackStatePlaying) { [playPauseButton setStyle:(UIBarButtonSystemItemPause)]; } else if (playbackState == MPMusicPlaybackStateStopped) { [playPauseButton setStyle:(UIBarButtonSystemItemPlay)]; [musicPlayer stop]; } } - (void) handle_VolumeChanged: (id) notification { [volumeSlider setValue:[musicPlayer volume]]; } #pragma mark - Media Picker - (IBAction)showMediaPicker:(id)sender { MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAny]; mediaPicker.delegate = self; mediaPicker.allowsPickingMultipleItems = YES; mediaPicker.prompt = @"Select songs to play"; [self presentViewController:mediaPicker animated:YES completion:nil]; } - (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection { if (mediaItemCollection) { [musicPlayer setQueueWithItemCollection: mediaItemCollection]; [musicPlayer play]; } [self dismissViewControllerAnimated:YES completion:nil]; } - (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker { [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark - Controls - (IBAction)volumeChanged:(id)sender { [musicPlayer setVolume:[volumeSlider value]]; } - (IBAction)previousSong:(id)sender { [musicPlayer skipToPreviousItem]; } - (IBAction)playPause:(id)sender { if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) { [musicPlayer pause]; } else { [musicPlayer play]; } } - (IBAction)nextSong:(id)sender { [musicPlayer skipToNextItem]; } @end ====Photos==== {{:user:asowers:photo_1_.jpg?300|}} {{:user:asowers:photo_3_.jpg?300|}} {{:user:asowers:photo_2_.jpg?300|}} {{:user:asowers:photo_4_.jpg?300|}} {{:user:asowers:photo_5_.jpg?300|}} {{:user:asowers:photo_6_.jpg?300|}} {{:user:asowers:photo_8_.jpg?300|}} {{:user:asowers:photo_7_.jpg?300|}}