UIImagePickerController crashes when using PhotoLibrary as source - ios

I'm using xcode 5.1 and tested the code both on ios7.1 and 7.0.2. The app crashes with UIImagePickerController in two scenarios on the device:
1) when allowsEditing is set to YES, after I crop a picture and press "Choose", as soon as it goes back to my own view, the app crashes
2) inside UIImagePickerController, when I go back from the photo list to the album list and I was at the bottom of the photo list, it crashes (no matter allowsEditing is YES or not). Note it does not crash if I scrolled the photo list up.
Here is my code:
- (IBAction)photoPickPressed:(id)sender {
if ([self isPhotoLibraryAvailable]) {
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.delegate = self;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.imagePicker.allowsEditing = YES;
NSString *requiredMediaType = (__bridge NSString*)kUTTypeImage;
self.imagePicker.mediaTypes = [[NSArray alloc] initWithObjects:requiredMediaType, nil];
[self presentViewController:self.imagePicker animated:YES completion:nil];
}
}
#pragma mark - image picker delegates
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
[picker dismissViewControllerAnimated:YES completion:^(){
NSLog(#"finished image picking");
});
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
[picker dismissViewControllerAnimated:YES completion:nil];
}
The crash message is
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSProxy doesNotRecognizeSelector:scrollViewDidScroll:] called!'
Note: it does NOT crash if I use camera even if I set allowsEditing to YES. Also it ONLY crashes on the real devices, not on the simulator.
Just to clarify (maybe unrelated), originally I declared the imagePicker as
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
, and it crashed. So I googled a lot, and a post says the controller might be recycled, and suggested to declare it in the class definition. So now I declared it in my class declartion:
#property (strong, nonatomic) UIImagePickerController *imagePicker;
Thanks in advance.
Update: I tried to even put the invoke of imagePickerController to the root view of my app, and it still crashes with the same message. I shouldn't have any scrollable view loaded yet.

After hours of investigation and tryout, I am confirmed that it is caused by a third-party framework integrated to the app: even that empty app crashes with UIImagePickerController if I link that framework there.
Thank you for the help!

My recommendation would be to remove the imagePickerController: didFinishPickingMediaWithInfo: method. It is completely optional, and will dismiss the image picker by default.
As well as this, I would recommend:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissViewControllerAnimated:YES completion:nil];
}
According to the documentation, this method should be called on the presenting view controller:
The presenting view controller is responsible for dismissing the view
controller it presented. If you call this method on the presented view
controller itself, it automatically forwards the message to the
presenting view controller.

Related

UIImagePickerController crashes on cancelling second time

I am using UIImagePickerController in my app and it crashes whenever I click on cancel for 2nd time and shows following crash log :
Terminating app due to uncaught exception
'UIViewControllerHierarchyInconsistency', reason: 'child view
controller: should have parent
view controller:(null) but actual parent is:'
Dismissing code :
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
The same code is working fine in other app but when I copied the code into new project the crash is occurring repeatedly.
Its happening on iOS 8.3 & 7.1, not tested on other versions.
Any help would be much appreciable.
Set delegate in .h
#interface YourViewController : UIViewController < UIImagePickerControllerDelegate, UINavigationControllerDelegate>
Initialize image picker when you want to open it.
UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
imgPicker.delegate = self;
imgPicker.allowsEditing = YES;
imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:imgPicker animated:YES completion:^{ }];
Delegate method
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:nil];
}

iOS Xcode issue with CameraViewController when I click on a photo to choose it

hoping for some insight. I have an issue with my Xcode app when I run it in simulator iPhone 6 iOS 8 or on my iPhone 4s iOS 8.0.2. The issue is that when I click on my photo tab to access CameraViewController the image picker code works fine in both situations (photo library for simulator and camera for iPhone)
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_imagePicker = [[UIImagePickerController alloc]init];
self.imagePicker.delegate = self;
self.imagePicker.allowsEditing = YES;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
else {
self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
self.imagePicker.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage, nil];
[self presentViewController:self.imagePicker animated:NO completion:nil];
}
Then when I click on a photo in simulator or take a photo with my iPhone and click on use photo the chosen image and fields that are there to be edited appears for a split second and then it goes back to image picker view to pick another photo (just keeps looping around like that.
here is my code for imagepickercontroller:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.chosenImageView.image = chosenImage;
[self dismissViewControllerAnimated:YES completion:nil];
}
Possible additional info in case you need it:
my Xcode is 6.0.1
my Base SDK is Latest iOS (iOS 8.0)
my Deployment Target 7.1
I did not alter any of these other than updating my when notified
any insight to fix this issue will be much appreciated
Grazie
The only problem I can see is that you are presenting the UIImagePickerContoller at ViewWillAppear or I can say you are performing the task of picking an image at ViewWillAppear.
ViewWillAppear gets called every time the ViewController will become active. This is leading your app in the loop of picking the image since the ViewWillAppear will be called again when the UIImagePickerController will be dismissed when didFinishPickingMediaWithInfo is called. Place a BREAK POINT at ViewWillAppear to check it yourself.
Try to move your code somewhere else other than ViewWillAppear.
You can place a button or something like that and write the same code in its -IBAction, that you have written in ViewWillAppear.

Can't dismiss UIImagePickerController

Edit: I just figured out the problem is UIImagePicker and not video editor changing code to represent that.
I am trying to make it so when they hit the cancel button on the UIImagepicker it will dismiss it and will logout of Facebook and go to the main view.
This is what I have to dismiss.
-(IBAction)Logout:(id)sender
{
[[FBSession activeSession]closeAndClearTokenInformation ];
[self.parentViewController dismissViewControllerAnimated:YES completion:nil];
[self.navigationController popToRootViewControllerAnimated:(YES)];
}
and here is how i present the image picker
//Create an image picker
UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
//Get the videos from the photo library
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
//Set media types to movie tyeps
imagePicker.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *) kUTTypeMovie, nil];
//present the controller
[self presentViewController:imagePicker animated:YES completion:nil];
The error I am getting is erminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSURL initFileURLWithPath:isDirectory:]: nil string parameter'
I am not even using initFileURLWithPath anywhere in my program so I have no idea what the problem seems to be right now. I have narrowed it down that the dismiss is causing the the error to happen and I'm not sure what is going wrong right now. Thanks.
Within your header file for your viewController you should already have the following delegates implemented
#interface ViewController : UIViewController<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
This will allow you access to the UIImagePickerController's delegate methods which will fire once the UIImagePicker cancel button has been pressed. One of these methods is the one below didFinishPickingMediaWithInfo. You will need to add this method and dismiss the picker from here.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
//Within this method you can capture/save etc the media you have just recorded etc too.
//Use the line below to dismiss the pickerController
[picker dismissViewControllerAnimated:YES completion:nil];
}
I hope this helps

Warning: Attempt to present <UINavigationController while a presentation is in progress

While trying to present the contact editor VC I get an error message of
Warning: Attempt to present <UINavigationController: 0x15fe273f0> on <UINavigationController: 0x15fe0e730> while a presentation is in progress!
I believe this is because my UIImagePickerController is still active.
Here is my didFinish method
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = info[UIImagePickerControllerOriginalImage];
animated:YES];
[picker dismissViewControllerAnimated:YES completion:NULL];
[self scanWithImage:image];
}
As you can see the second message should dismiss the VC but it does not, and it stays up until the end of the execution of the application.
scanWithImage: eventually calls showNewPersonViewController here is that method:
-(void)showNewPersonViewController
{
ABNewPersonViewController *picker = [[ABNewPersonViewController alloc] init];
picker.displayedPerson = _person;
picker.newPersonViewDelegate = self;
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:picker];
// Change status bar back to black due to white contact creation.
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
[self presentViewController:navigation animated:YES completion:nil];
}
On the last line in that method I get the error message, then the app finishes its execution and returns to the main VC.
How can I avoid this and properly display the contact creation VC?
Let's try:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = info[UIImagePickerControllerOriginalImage];
// I think picker should change to self == this class dismisses, not picker dismisses
[self dismissViewControllerAnimated:YES completion:nil];
}
// should implement [self scanWithImage:image]; in parent class which contains VC has pickerView.
// Because after dismissing, VC which contains picker is dealloc, how can you call [self presentViewController:navigation animated:YES completion:nil];
I think this can help you
I think you are presenting two VCs at same time with animation.
Set one of VC's animation to NO while presenting or dismissing and see if the warning goes away.
I'm not 100% sure but if you want both animations you should run the second one on the first one's completion block or use a timer to delay the second view controller's navigation start.

UIImagePickerController error: Snapshotting a view that has not been rendered results in an empty snapshot in iOS 7

I am getting this error only in iOS 7 and the application crashed.
In iOS 6, I never get any error, just once of memory warning when opening the camera.
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
Here is what I am doing.
imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setAllowsEditing:YES];
[self presentModalViewController:imagePicker animated:YES];
I did tried to delay the presentModalViewController, but I am still getting the same message. After few seconds (7-10), the application crashed.
This error is only present in iOS 7.
Anybody has the clue?
The problem in iOS7 has to do with transitions. It seems that if a previous transition didn't complete and you launch a new one, iOS7 messes the views, where iOS6 seems to manage it correctly.
You should initialize your Camera in your UIViewController, only after the view has Loaded and with a timeout:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//show camera...
if (!hasLoadedCamera)
[self performSelector:#selector(showcamera) withObject:nil afterDelay:0.3];
}
and here is the initialization code
- (void)showcamera {
imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setAllowsEditing:YES];
[self presentModalViewController:imagePicker animated:YES];
}
This error also showed up for me with Apple's PhotoPicker sample code project.
I was using Xcode Version 5.0 and iOS 7.0.3 on an iPhone 4.
Steps to Reproduce:
Download Apple's PhotoPicker sample project at
https://developer.apple.com/library/ios/samplecode/PhotoPicker/Introduction/Intro.html
In APLViewController.m comment out line 125
//imagePickerController.showsCameraControls = NO;
In APLViewController.m comment out lines 130-133
//[[NSBundle mainBundle] loadNibNamed:#"OverlayView" owner:self options:nil];
// self.overlayView.frame = imagePickerController.cameraOverlayView.frame;
// imagePickerController.cameraOverlayView = self.overlayView;
// self.overlayView = nil;
Build and launch the app.
Once launched, rotate device to Landscape mode.
Click Camera icon to open UIImagePickerController in Camera mode.
View the console output.
Console output
PhotoPicker[240:60b] Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
showsCameraControls property
The problem occurs for me when this has a value of YES (the default).
Setting this to NO eliminated the message.
Bug report
I just filed a bug report with Apple.
I've tried many of the suggestions that have been made in different posts, but have not found a satisfactory workaround.
I got the problem when I tried to present the camera view inside of a popover. Under iOS6 this was no problem but in iOS7 I got the message
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
as well.
However after I changed the presentation of the camera view to fullscreen as described in Taking Pictures and Movies, iOS Developer Library everything went fine again and the message never appeared again. However I had to make sure that depending on in which mode the app is (i.e., presenting camera view or photo roll) I had to either dismiss the popover or the view controller whenever the method - (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker was called.
create a property
#property (nonatomic) UIImagePickerController *imagePickerController;
Then
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.modalPresentationStyle = UIModalPresentationCurrentContext;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = YES;
self.imagePickerController = picker;
[self presentViewController:self.imagePickerController animated:YES completion:nil];
This should solve the problem
I used this code to workaround the problem:
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setDelegate:self];
if ([self respondsToSelector:#selector(presentViewController:animated:completion:)]){
[imagePicker setShowsCameraControls:NO];
[self presentViewController:imagePicker animated:YES completion:^{
[imagePicker setShowsCameraControls:YES];
}];
} else {
[imagePicker setShowsCameraControls:YES];
[self presentModalViewController:imagePicker animated:YES];
}
I have the same issue and found a solve. I think, that error related with orientation of your application. My application uses only landscape mode, but UIImagePickerController use portrait mode. I add try-catch block to main.m, and get real exception:
Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES
How i solve this problem:
1) Recheck device orientation in Target->General, or .plist file: Supported interface orientations : Landscape left, Landscape right.
2) Add in AppDelegate.m:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskLandscape | UIInterfaceOrientationMaskPortrait;
}
After this step UIImagePickerController works properly, but my viewcontrollers can be rotated to portrait mode. So, to solve this:
3) Create a category for UINavigationController, (supportedInterfaceOrientations moved from UIViewController to UINavigationController in iOS6):
#implementation UINavigationController (RotationIOS6)
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
#end
This solution works properly on iOS 6.0, 6.1, 7.0. Hope this helps.
I get this error when building app with iOS SDK 6.1, deployment target iOS 6.1 and running app on iOS 7 powered iPhone. App doesn't crash but implementing UIViewController shouldAutorotate method helps me to remove error message.
- (BOOL)shouldAutorotate {
return YES;
}
I had the same issue when I was trying to modify the demo app that come with the Avirary SDK,
in the demo app, it can only edit the photo picked from the camera roll. To try to edit the photo by capturing from camera, I first added the following code in the UIViewcontroller.m file:
#pragma mark - Take Picture from Camera
- (void)showCamera
{
//[self launchPhotoEditorWithImage:sampleImage highResolutionImage:nil];
if ([self hasValidAPIKey]) {
UIImagePickerController * imagePicker = [UIImagePickerController new];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setDelegate:self];
[imagePicker setAllowsEditing:YES]; //important, must have
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[self presentViewController:imagePicker animated:YES completion:nil];
}else{
[self presentViewControllerInPopover:imagePicker];
}
}
}
Then when I run the app, the error occurred:
Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.
To solve the error, modified the UIImagePicker delegate in your UIViewContooler.m file as shown below:
#pragma mark - UIImagePicker Delegate
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSURL * assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
void(^completion)(void) = ^(void){
[[self assetLibrary] assetForURL:assetURL resultBlock:^(ALAsset *asset) {
if (asset){
[self launchEditorWithAsset:asset];
}
} failureBlock:^(NSError *error) {
[[[UIAlertView alloc] initWithTitle:#"Error" message:#"Please enable access to your device's photos." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}];
UIImage * editedImage = [info objectForKey:UIImagePickerControllerEditedImage];
if(editedImage){
[self launchPhotoEditorWithImage:editedImage highResolutionImage:editedImage];
}
};
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[self dismissViewControllerAnimated:YES completion:completion];
}else{
[self dismissPopoverWithCompletion:completion];
}
}
Then the error disappeared and the app works!
Try this, use
[self performSelector:#selector(presentCameraView) withObject:nil afterDelay:1.0f];
and function
-(void)presentCameraView{
[self presentViewController:imagePicker animated:YES completion:nil];
}
to replace. [self presentModalViewController:imagePicker animated:YES];
and of cause make imagePicker as a global variable.
This is what fixed it for me on my app, ymmv
first off it is a iPhone - iPad app
in appname-Info.plist. in the Supported interface orientations(iPad) showed 4 orientations.
in the Supported interface orientations showed 3 orientations. I added the fourth and ran the app, no debug output.
Hope this helps.
I've just encountered the same issue. In my case the problem was that I had some non-ARC code and I've migrated it to ARC. When I did the migration, I didn't hold a strong reference to the UIImagePickerController and that was the reason for the crash.
Hope it helps :)
I had same issue in iOS 8, But the Camera Access was Disable inside Settings--> Privacy for my App. Just Enabled it, and It was working.
I spent long time try to find the solution, and surprisingly I have found it at the end and it was just very funny once I discovered it.
Here is what you will do to retrieve the image you picked and resume working :)
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
UIImage* pickedImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
[composeImageView setImage:pickedImage];
[picker dismissViewControllerAnimated:YES completion:nil];
}
Yes, to solve the issue, you only need to dismiss the picker normally as it seems this message: "Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates." stops the picker from being responsive but you can dismiss it and retrieve the image normally.
In my case it was related with a layout change: the VC presenting the UIImagePickerViewController has the status bar hidden, but the UIImagePickerViewController hasn't.
So, I solved it hiding the status bar in the UIImagePickerViewController as it's shown in this answer.
Not directly answering your question but you mentioned you had a memory warning ,you might be storing the raw image in a property which can lead to a memory warning. This is because the raw image takes up roughly 30MB of memory. I noticed a similar memory warning when testing apps on iOS6 which were on the iPhone 4 series. I still got this warning when the devices were upgraded to iOS7. There is no memory warning when testing on iPhone 5 series on iOS7.
Changing
[self presentViewController:imagePicker animated:YES completion:nil];
to
[self presentViewController:imagePicker animated:YES completion:NULL];
fixed the issue for me.

Resources