Friday, September 10, 2010

"UIImagePickerController does not work"!

Here is another common mistake that I have seen with UIImagePickerController. Say, I want to display the picked image in the UIImageView (imageView), but it doesn't work. It is a simple issue, can anybody guess what the problem is before you see the answer below?
- (IBAction)takePhoto {

     UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
     imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
     [self presentModalViewController:imagePicker animated:YES];
     [imagePicker release];

- (IBAction)choosePhoto {

     UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
     //imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
     [self presentModalViewController:imagePicker animated:YES];
     [imagePicker release];

- (void)imagePickerController:(UIImagePickerController *)imagePicker didFinishPickingMediaWithInfo:(NSDictionary *)info {

     UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
     imageView.image = image;

     [self dismissModalViewControllerAnimated:YES];

We have not set the delegate! So no call backs being obtained! Just add : 
 imagePicker.delegate = self;

UIImagePickerController strange behavior

Here is a piece of UIImagePickerController source code. The source code is really straight forward. Say, we have a ViewController and in the .m file, we declare the following information:LoadCamera is a function that open the initiates the UIImagePickerController and adds it to the delegate's window. What's wrong with the code? 

-(IBAction)loadCamera:(UIButton *)sender{
     PagingScrollViewAppDelegate *appDelegate = (PagingScrollViewAppDelegate *)[[UIApplication sharedApplication] delegate];

     imagePickerController = [[UIImagePickerController alloc] init];
     imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
     imagePickerController.delegate = self;
     [appDelegate.window addSubview:imagePickerController.view];
The strange thing occurs when I select an image inside the UIImagePickerController, instead of calling the
- (void)imagePickerController:(UIImagePickerController *)picker 
          didFinishPickingImage:(UIImage *)image
                      editingInfo:(NSDictionary *)editingInfo
it calls the

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
Basically, it is due to the fact that we are adding the UIImagePickerController's view as a subview of the main view.
UIImagePickerController should be presented modally. Else, it gives strange behavior! 

Hope that helps!

UIViewController *viewController = [[[UIViewController alloc] initWithNibName:nil bundle:nil] autorelease];
self.navController = [[[UINavigationController alloc]           
                           initWithRootViewController:viewController] autorelease ];
[appDelegate.window addSubview: [navController view]];
[navController presentModalViewController:myImagePicker animated: YES];

Thursday, September 9, 2010

NSLog tricks: Log only in Debug mode. Add Function name, Line num

It is a common requirement to log certain statements only in the Debug mode, while needing to avoid them in the release mode. Of course, one option is to have statements like this everywhere:

NSLog(@"Data: point.x = %f, point.y = %f", point.x, point.y);
And define DEBUGGING somewhere in the header file. However, this can get very verbose. 
A better option is to use Macros. In project_Prefix.pch file, include: 

# define DBLog(fmt,...) NSLog(@"%@",[NSString stringWithFormat:(fmt), ##__VA_ARGS__]);
# define DBLog(...)
Also, you can include, in "Edit Active Target" -> "Build" -> (Select Debug Config) -> "Other C/C++ Flags", write:


This automatically defines DEBUGGING flag in Debug mode. Leave it blank for the Release mode.  

Now, you can use DBLog instead of NSLog: 

DBLog(@"Data: point.x = %f, point.y = %f", point.x, point.y);

This will automatically print statements in the Debug mode, and not print the statements in the Release mode! 

(Alternatively, you can have a line in the Prefix.pch file:
#define DEBUGGING 
And manually comment it out for Release mode.)

Similarly, if you want you also have function name and line number, there is a nice trick:

#ifdef DEBUGGING#   define DLog(fmt, ...) NSLog((@"Func: %s , Line: %d, " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#   define DLog(...)

If you always want to print out regardless of the DEBUGGING SETTING, but with the function name and line number:
#define ALog(fmt, ...) NSLog((@"Func: %s , Line: %d, " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
Hope that helps! Happy iCoding!