Saturday, May 25, 2013

Custom Push in/out Transition Animation for Modal View Controllers

Implementing a custom transition animation for view controllers is not too difficult. Let's consider that we need to push from right/left when presenting a modal view controller, and then pushing out to the other direction when dismissing the dialog. The below mentioned UIViewController category serves this purpose for us.

@interface UIViewController (Transitions)

- (void) presentModalViewController:(UIViewController *)modalViewController withPushDirection: (NSString *) direction;
- (void) dismissModalViewControllerWithPushDirection:(NSString *) direction;

@end  

and the implementation:

#import "UIViewController+Transitions.h"

@implementation UIViewController (Transitions)

- (void) presentModalViewController:(UIViewController *)modalViewController withPushDirection: (NSString *) direction {
    
    [CATransaction begin];
    
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = direction;
    transition.duration = 0.25f;
    transition.fillMode = kCAFillModeForwards;
    transition.removedOnCompletion = YES;
    
    [[UIApplication sharedApplication].keyWindow.layer addAnimation:transition forKey:@"transition"];
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    [CATransaction setCompletionBlock: ^ {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(transition.duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^ {
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];
        });
    }];
    
    [self presentViewController:modalViewController animated:NO completion:nil];
    
    [CATransaction commit];
    
}

- (void) dismissModalViewControllerWithPushDirection:(NSString *) direction {
    
    [CATransaction begin];
    
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = direction;
    transition.duration = 0.25f;
    transition.fillMode = kCAFillModeForwards;
    transition.removedOnCompletion = YES;
    
    [[UIApplication sharedApplication].keyWindow.layer addAnimation:transition forKey:@"transition"];
    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    [CATransaction setCompletionBlock: ^ {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(transition.duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^ {
            [[UIApplication sharedApplication] endIgnoringInteractionEvents];
        });
    }];
    
    [self dismissViewControllerAnimated:NO completion:nil];
    
    [CATransaction commit];
    
}

@end

To use it, you import "UIViewController+Transitions.h" in your file and call the presentModalViewController:withPushDirection:
the direction parameter receives core animation transition sub-types such as kCATransitionFromRight.
You can download the category files from here and import to your project.

Enjoy...

Thursday, May 23, 2013

IPhone: Playing Basic Audio

This post is for beginner level programmers and hence I won't go into complex audio using OpenAL or Audio Queues. Today, we will just be playing short sounds (less than 30 seconds). This will be the easiest way to do audio if you don’t require any background/continuous music. However, the downfall of doing audio this way is only one audio file can be playing at a time.

Let's get started

Lets assume the two sounds we want to play are:
* drumSound.caf
* pianoSound.caf


Notice that both of the audio files have a .caf extension. This is the audio type all of your sound files must be in to be played by the iPhone. Luckily Apple has provided us a utility for converting audio to this format. You can read up on it here. It’s pretty straight forward, just open up a Terminal and type:

/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}

where {INPUT} is the path to your input audio file and {OUTPUT} is the file you want it to save it to with a .caf extension.

Step 1: Adding Audio Files
Drag the required audio files to your Resources Folder inside of your project. Make sure you check the box to copy the files into your project’s directory.

Step 2: Add The AudioToolbox.framework to Your Project
Right Click on the Frameworks folder in your project and select Add -> Existing Frameworks. Search for AudioToolbox.framework and when found click Add.

Step 3: Add the Header Declarations
Open up your ViewController and add the following code into its .h file

#import


SystemSoundID drumSoundID;
SystemSoundID pianoSoundID;

@property(nonatomic) SystemSoundID drumSoundID;
@property(nonatomic) SystemSoundID pianoSoundID;


Now open up the .m file of the same ViewController and add the following code:
@synthesize drumSoundID, pianoSoundID;


Now add the following code in viewDidLoad method to initialize our sounds object.


NSString *drumPath = [[NSBundle mainBundle] pathForResource:@"drumSound" ofType:@"caf"];
CFURLRef drumURL = (CFURLRef) [NSURL fileURLWithPath:drumPath];
AudioServicesCreateSystemSoundID (drumURL, &drumFileID);

NSString *pianoPath = [[NSBundle mainBundle] pathForResource:@"pianoSound" ofType:@"caf"];
CFURLRef pianoURL = (CFURLRef) [NSURL fileURLWithPath:pianoPath];
AudioServicesCreateSystemSoundID (pianoURL, &pianoFileID);


The first line gets the path of the audio file. The next line converts the path to a CFURLRef. Finally, we load that audio file and associate it with the given sound ID. Notice we pass &drumFileID. This is a pass by reference and allows the AudioServicesCreateSystemSoundID method to modify this variable. We do the same thing to load the volley sound. Now, let’s play the sounds.

Step 4: Playing the Sounds
t’s actually quite simple to play the sounds we have loaded. Simply call the AudioServicesPlaySystemSound method and pass it the soundID of the file you want to play. So to play the drum sound, just call this method:


-(void)playDrumSound {
AudioServicesPlaySystemSound (drumFileID);
}


Same way we could play the other sound anytime depending on our requirement. This tutorial would help you in adding any basic audio to your project.