iPhone: UIImagePickerController Randomly Fails to Take Picture - iphone

I use a UIPickerViewController to take picture. It works 80% but seemingly at random it fails to take a picture. In tracing the code I found out that it occasionally goes to
-PinRecordNewTableViewController:viewDidUnload.
That is where it fails because it set nil to all ivars.
#interface PinRecordNewTableViewController : UITableViewController {
}
...
#implementation PinRecordNewTableViewController
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
PinRecordNewPicture *pinRecordNewPicture = [[PinRecordNewPicture alloc] initWithNibName:#"PinRecordNewPicture" bundle:nil];
pinRecordNewPicture.delegate = self;
[self.navigationController pushViewController:pinRecordNewPicture animated:YES];
[pinRecordNewPicture release];
...
}
#interface PinRecordNewPicture : UIViewController
...
#implementation PinRecordNewPicture
...
- (void)picturePicker:(UIImagePickerControllerSourceType)theSource {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = theSource;
picker.allowsEditing = YES;
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (IBAction) takePicture:(id)sender {
UIImagePickerControllerSourceType source = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable:source]) {
[self picturePicker:source];
}
What did I do wrong? Did I miss something that causes it to behave "randomly"?
Thanks in advance for your help.

If it called viewDidUnload, then it is very likely that your app is running out of memory. This could be a problem, or just the result of editing large images in phone.

If you're trying to take multiple pictures, save the current one to the Documents area of the app. It frees up the memory. This way, the memory warning can be avoided.
If ViewDidUnload is being called, you might think about saving the relevant state of the app in didReceiveMemoryWarning and restoring it in viewDidLoad. This is done using NSUserDefaults class

Related

Best way to use imagepickercontroller in iphone?

I am using UIImagePickerController to select the image from the PhotoLibrary in my application. I have used two different approaches for this. At first I have used a class variouble UIImagePicker with below code.
imagepicker = [[UIImagePickerController alloc]init];
imagepicker.delegate = self;
imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagepicker.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:self.imagepicker animated:YES];
Above code is working fine.But when I clicked on the button it is taking some time to react with the animation in this case.Then I used the autorelease pool approach with this method
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
if([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypePhotoLibrary])
{
UIImagePickerController *picker= [[[UIImagePickerController alloc]init]autorelease];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:picker animated:YES];
}
[pool release];
Also works charm. Both of them showing no leak in the analyser.Can anybody point me the right approach.
Well, no much to say here... Both approaches work, both approaches are correct, use whichever you prefer.
One minor point: if you are regularly presenting the image picker, you better use the first method, and assign it to an instance variable (it isn't called a "class variable"!) only for the first time, and don't release it until - dealloc - this way, you save the continuous allocation-deallocation of the image picker every single time the user chooses an image.

how to fix iOS leak when flipping between two views

My iPhone app badly leaks when flipping back and forth between a main uiviewcontroller and a help uiviewcontroller .
Here is the source of the main view, followed by source of the help view.
MAIN VIEW - FLIP TO HELP.....................
// Changes from operational view to Help view.
- (IBAction)showHelp:(id)sender
{
// End trial mode:
self.stop_trial_if_started;
self.rename_trial_if_edited;
// Switch to trial help:
help_view_context = 0;
HelpView *controller = [[HelpView alloc] initWithNibName:#"HelpView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
HELP VIEW - INIT.............................
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
help_scroll.editable = FALSE;
return;
}
HELP - RETURN TO MAIN VIEW.........................
// User clicked the button to return to operational view:
- (IBAction)done:(id)sender {
NSLog(#"help- done");
if( help_view_context == 0 ) {
[self.delegate trial_help_DidFinish:self];
}else{
[self.delegate file_help_DidFinish:self];
}
}
MAIN VIEW - RETURN FROM HELP...............................
// Inits operational view when user changes from Help view back to operational view.
- (void)trial_help_DidFinish:(HelpView *)controller {
NSLog(#"trial_help_DidFinish");
[self dismissModalViewControllerAnimated:YES];
self.init_trial_operation;
}
You are creating a controller with ref count of 1 and a local reference each time showHelp: is called:
HelpView *controller = [[HelpView alloc] initWithNibName:#"HelpView" bundle:nil];
you are losing your reference to it at the end of this method.
You happen to have references to it in done: (self) and *_help_didFinish (controller), but you never release it in either of those locations. Dismissing the controller is fine, but you also have to release it.
(Another option would be to never create a second one, and maintain an iVar to the original.)
You could well be leaking on this line
controller.delegate = self;
What is your property declaration for the delegate. If it's anything other than assign, then you either need to change it (preferred option) or make sure you are releasing it in the dealloc method of HelpView controller.

Load UIImagePickerController in background

When my app starts I would like to initialize an UIImagePickerController. Since this can take several seconds, I would like to do it in the background. What is the best way to ensure that the background task finished, before invoking the picker?
Currently I have the following code. It works, but it will crash if one invokes the picker before the background task is done.
- (void) viewDidAppear: (BOOL)animated {
[super viewDidAppear: animated];
[self performSelectorInBackground:#selector(initPicker) withObject:nil];
....
}
and
- (void) initPicker {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"picker start... ");
[self setPicker: [[UIImagePickerController alloc] init]];
NSLog(#"picker done.");
[pool release];
}
Thank you!
Edit: It turns our this question is somewhat theoretical. Computing [[UIImagePickerController alloc] init] only takes time in debug mode on the device. So for production code, there is no need to run anything in the background. Also, [[UIImagePickerController alloc] init] seems to lock the main thread, so even in debug mode there is no advantage of placing it on a background thread.
Maybe a simple flag can do the job ?
#interface MyViewController : UIViewController
{
BOOL _pickerIsLoaded;
}
#end
#implementation MyViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
_pickerIsLoaded = NO;
[self performSelectorInBackground:#selector(initPicker) withObject:nil];
}
- (void)initPicker
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"picker start... ");
[self setPicker: [[UIImagePickerController alloc] init]];
NSLog(#"picker done.");
_pickerIsLoaded = YES;
[pool release];
}
#end
I would use NSConditionLock for signaling that your controller is loaded. In the -initPicker method I would set the condition when the UIImagePickerController is finish initializing. And in your IBAction for the showing the picker, I would check for that condition. For more options, see Threading Programming Guide.
Can you wait until your "picker done" and then add the picker view to whatever view makes it visible?
Something like this, right after your "picker done" statment:
[self presentModalViewController: theImagePickerController]; // assuming self is a viewController.

Using UIImagePickerController in the game

I want to make a game, where the user can touch a picture of a TV and then choose a picture from their photo library.
I had success working with UITextFields, adding them to my EAGLView as subviews But I haven't been able to do the same thing with an UIImagePickerController , which seems the only way to do what I want to do.
Any help is appreciated !
UPDATE
With the suggestion of zpasternack I managed to make the menu appear by adding the UIImagePickerControllerDelegate, UINavigationControllerDelegate and using this method:
- (void) chooseImageFromLibrary {
if( ![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary] ) return;
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.allowsEditing = YES;
[self addSubview:imagePickerController.view];
[imagePickerController viewWillAppear:YES];
[imagePickerController viewDidAppear:YES];
}
I call the chooseImageFromLibrary method at the start. It shows the interface, but as soon as i hit cancel or choose the app stops.
Can anyone suggest me:
1) How to make the cancel and choose buttons work.
2) How to call the UIImagePickerController whenever I want ( by calling chooseImageFromLibrary again ??).
3) When the user hits choose..Where do i find the UIImage the user just picked to ?, how do i pick it ?
Thanks.
I've never used one over an EAGLView, but UIImagePickerControllers are typically invoked with presentModalViewController, like:
- (void) chooseImageFromLibrary {
if( ![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary] ) return;
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.allowsEditing = YES;
[self presentModalViewController:imagePickerController animated:YES];
}
Nervermind, problem solved. i just needed to overwrite some functions to make use of the UIImagePickerController.

iPhone dev noob question: Invoking action explicitly on application launch

I just started getting into iPhone development. I have been mish-mashing tutorials and material from books in order to get my bearings straight. I come from a PHP and Java background... Objective-C is a bit quirky. But, I learn best by getting my feet wet.
Basically, I have these actions. getPhoto is bound to a couple of UIBarButtonItems in my view.
-(IBAction) getPhoto:(id) sender {
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
if((UIBarButtonItem *) sender == choosePhoto) {
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
} else {
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
[self presentModalViewController:picker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
theimageView.image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
My goal is to invoke the same action once the application launches, automatically opening the Camera. How would I go about this?
EDIT:
As per this SO question you should actually place it in viewWillAppear or viewDidAppear
Add a similar method to the ApplicationDidFinishLaunching method in the app delegate.
Might be better to place the call in the ViewDidLoad of your root view controller