Strange Error With UIPopoverController - objective-c

I'm trying to use UIImagePickerController to grab a photo from the users Photos on their iPhone / iPad. This code works just fine for iPhone, but when I run it on iPad, the debugger gives me the message "Terminating app due to uncaught exception 'NSGenericException', reason: '-[UIPopoverController dealloc] reached while popover is still visible.". I'm very new to Objective-C, so I'm unsure of whats causing this, I do not dealloc anything and I have ARC turned on. Here is my code:
ViewController.m
#import "PhotoViewController.h"
#implementation PhotoViewController
#synthesize grabButton;
#synthesize image;
#synthesize imgPicker;
- (IBAction)grabImage {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
[popover presentPopoverFromRect:self.image.bounds inView:self.image permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
} else {
[self presentModalViewController:imgPicker animated:YES];
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
image.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
- (void)viewDidLoad
{
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.allowsImageEditing = YES;
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}

UIPopover is an ugly patchwork beast of an object. It must be a strong property and an iVar to ensure that Dealloc isn't reached prematurely. Add this in the .h Like so:
#interface MyClass: NSObject {
UIPopover *_popover;
}
#property (nonatomic, strong) UIPopover * popover;
//.m
#synthesize popover = _popover;
When you instantiate the popover, assign it to either the property or the instance:
self.popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
or
_popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];

Related

ImagePickerController crash presentViewController when called in UIStoryboardPopoverSegue

I have a viewcontroller called via UIStoryboardPopoverSegue and inside there is a button to call the imagePickerController, it's ok for the first call but the second time it crash.
The code is use is ok when it is not through UIStoryboardPopoverSegue.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image=[info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum (image, nil, nil , nil);
[self dismissViewControllerAnimated:YES completion:nil];
}
-(IBAction)takephoto:(id)sender
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.imagePicker.delegate=self;
self.imagePicker.sourceType=UIImagePickerControllerSourceTypeCamera;
[self presentViewController:imagePicker animated:YES completion:nil];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (!self.imagePicker)
{
self.imagePicker = [[UIImagePickerController alloc] init];
}
}
I enabled NSZobmbie to show any log that can help me tracing it.
* -[UIImagePickerController isKindOfClass:]: message sent to
deallocated instance 0x1eb3b700
Your UIImagePickerController is released and then attempted to be accessed later - so crashes!
To fix it, make the UIImagePickerController a strongly referenced property of the owning instance:
#property (strong, nonatomic) UIImagePickerController *imagePicker;
initialise it once:
if (!self.imagePicker) self.imagePicker = [[UIImagePickerController alloc] init];
and use:
[self.imagePicker doStuff]
for access.
That should solve it.
EDIT
if ([[segue identifier]isEqualToString:#"tcwindshield"]) {
self.ips = [segue destinationViewController];
self.ips.delegate = self
self.ips.strStatValue=#"WindShield";
}

Can't override a simple method

I've created a new project with two ViewControllers and imported a class that pushes ViewController from right to left instead LTR but can't manage to use it. I can see that pushViewController inside UIRightToLeft.m is not being called and I don't understand why.
My main goal is to get that working with RTL aniamtion.
#import "UIRightToLeft.h"
#implementation UIRightToLeft
- (id)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if (!self)
return nil;
return self;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
NSLog(#"pushViewController");
// Add the viewController and a fake controller without animation. Then pop the fake controller with animation.
UIViewController *fakeController = [[UIViewController alloc] init] ;
[super setViewControllers:[[self viewControllers] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:viewController, fakeController, nil]] animated:NO];
[super popViewControllerAnimated:animated];
}
- (void)popViewControllerAnimatedStep2:(UIViewController *)viewController
{
// Push the new top controller with animation
[super pushViewController:viewController animated:YES];
// Remove the view that should have been popped
NSMutableArray *arr = [NSMutableArray arrayWithArray:[self viewControllers]];
[arr removeObjectAtIndex:[[self viewControllers] count]-2];
[super setViewControllers:[NSArray arrayWithArray:arr] animated:NO];
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
NSLog(#"popViewControllerAnimated");
if (animated)
{
// Save the controller that should be on top after this pop operation
UIViewController *newTopController = [[self viewControllers] objectAtIndex:[[self viewControllers] count]-2];
// Remove it from the stack. Leave the view that should be popped on top
NSMutableArray *arr = [NSMutableArray arrayWithArray:[self viewControllers]];
[arr removeObjectAtIndex:[[self viewControllers] count]-2];
[super setViewControllers:[NSArray arrayWithArray:arr] animated:NO];
// Schedule the next step
[self performSelector:#selector(popViewControllerAnimatedStep2:) withObject:newTopController afterDelay:0];
return [arr objectAtIndex:[arr count]-1];
}
return [super popViewControllerAnimated:NO];
}
#end
ViewController.m:
#import "ViewController.h"
#import "UIRightToLeft.h"
#import "SecondViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)pressMe:(UIButton *)sender {
SecondViewController *next = [[SecondViewController alloc]init];
[self.navigationController pushViewController:next animated:YES];
}
#end
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
- (IBAction)pressMe:(UIButton *)sender;
#end
(In my ViewController there's only one button draged to the second ViewController with push)
After looking at your error log I think you actually need to have your navigation controller subclass UIRightToLeft.
If you are using a Storyboard, select your navigation controller and set Custom Class to UIRightToLeft.

iOS: UIImagePickerController Issue

I'm trying to use UIImagePickerController to grab a photo from the users Photos on their iPhone / iPad. This code works just fine for iPhone, but when I run it on iPad, the debugger gives me the message "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'On iPad, UIImagePickerController must be presented via UIPopoverController'". I'm very new to Objective-C, so I'm unsure of how to edit this code to use UIPopoverController when its being run on the iPad. I'd rather not create 2 new View Controllers, so I was wondering if someone knows what code I would need to add in to have it work on both the iPhone and iPad. Here is the code in my view controllers:
ViewController.h:
#interface PhotoViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate> {
UIButton *grabButton;
UIImageView *image;
UIImagePickerController *imgPicker;
}
#property (strong, nonatomic) IBOutlet UIButton *grabButton;
#property (strong, nonatomic) IBOutlet UIImageView *image;
#property (strong, nonatomic) UIImagePickerController *imgPicker;
- (IBAction)grabImage;
#end
ViewController.m:
#import "PhotoViewController.h"
#implementation PhotoViewController
#synthesize grabButton;
#synthesize image;
#synthesize imgPicker;
- (IBAction)grabImage {
[self presentModalViewController:self.imgPicker animated:YES];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
image.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Photo Gallery", #"Photo Gallery");
self.tabBarItem.image = [UIImage imageNamed:#"42-photos.png"];
}
return self;
}
- (void)viewDidLoad
{
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.allowsImageEditing = YES;
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[super viewDidLoad];
}
Thanks in advance!
You have the answer through that error message !
Use UIPopOverController with UIImagePicker for iPad.
If you want to know how to use UIPopOverController, you can look at this tutorial !
Another youtube tutorial - http://www.youtube.com/watch?v=6Gc3kxVwfmE
Like Legolas mentioned, in an iPad app you must use a UIPopOverController in order to present an imagePicker. I'm usually not a fan of having any code in my app that performs tasks based on device type, but if you don't find a better solution you can do the following.
if ([[UIDevice currentDevice].model isEqual:#"iPad"])
{
// Display image picker in a popover
}
else
{
// display imagePicker as a modal
}
Check the documentation for device models:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html
It's worked for me. Please try below code
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:self.imgpicker];
popover.delegate =self;
[popover presentPopoverFromRect:self.view.bounds inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];}else{
[self presentModalViewController:self.imgpicker animated:YES];
}

iOS: UIPopoverController Error

I'm trying to make my application grab a photo from the user's Photo library using UIImagePickerController and display it in the app. My code works great for the iPhone, but I need to use UIPopoverController for the iPad. I'm still very new to programming in general, so I'm having a really difficult time trying to figure out how to do this. While testing it out, I ran into a strange error. The debugger says "Terminating app due to uncaught exception 'NSGenericException', reason: '-[UIPopoverController dealloc] reached while popover is still visible." but I don't dealloc anything, I have ARC turned on. Here is my code:
ViewController.m:
#import "PhotoViewController.h"
#implementation PhotoViewController
#synthesize grabButton;
#synthesize image;
#synthesize imgPicker;
- (IBAction)grabImage {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
[popover presentPopoverFromRect:self.image.bounds inView:self.image permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
} else {
[self presentModalViewController:imgPicker animated:YES];
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
image.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
- (void)viewDidLoad
{
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.allowsImageEditing = YES;
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
Any help is much appreciated! Thank you!
Ray Wenderlich has a nice tutorial on UIPopoverControllers here: http://www.raywenderlich.com/1056/ipad-for-iphone-developers-101-uipopovercontroller-tutorial

Xcode SIGABRT when accessing photo gallery

I've been trying to get my application to select a photo from the photo gallery and then display it, it worked in a different project fine, but in this one the application runs fine but when I press the UIButton that is supposed to bring up the gallery, I get the error SIGABRT in main.m on int retVal = UIApplicationMain(argc, argv, nil, nil);
As I said, this has worked fine in the past so I don't know why it isn't now, here's the parts of the code related to the error, I'm only posting that as I've got a lot of code and it's easier this way.
ViewController.h
#import <UIKit/UKit.h>
#interface ViewController : UIViewController
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
//Blah blah blah
}
//Blah blah blah
-(IBAction) selectExistingpicture;
#property (nonatomic, retain) IBOutlet UIImageView *theImageView;
//Blah blah blah
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize theImageView;
-(IBAction) selectExistingPicture
{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary])
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentModalViewController:picker animated:YES];
[picker release];
}
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage : (UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
theImageView.image = image;
[picker dismissModalViewControllerAnimated:YES];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *) picker
{
[picker dismissModalViewControllerAnimated:YES];
}
I have linked selectExistingPicture to a UIButton but I don't know what's causing that button to cause me errors.
Any help is greatly appreciated.
Here is how i use my camera roll
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, (NSString *) kUTTypeMovie,
nil];
imagePickerController.delegate = self;
[self presentModalViewController:imagePickerController animated:YES];
}
else {
NSLog(#"Error");
}
the thing that i see wrong with yours is
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
which should be
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
Also you appear to be missing
imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, (NSString *) kUTTypeMovie,
nil];
Take a look at how i have mine set up
Your problem has nothing to do with the photo gallery. It probably never executes selectExistingPicture in the first place.
Possible problems:
The view controller isn't an instance of ViewController because you didn't specify the correct class in IB.
You write selectExistingpicture instead of selectExistingPicture (lower vs. upper case P) in a few places.
selectExistingpicture != selectExistingPicture...
that is you declare selectExistingpicture then define selectExistingPicture which is why your autocomplete would select selectExistingpicture for you, as it exists in your .h file, this mis-match will cause a compiler warning... change all instances to proper camelCased selectExistingPicture and you will be fine... well at least that error will go away.
As others noted, you have a typo (incorrect case on selectExistingPicture), noted for you right there in the error message:
reason: '-[ViewController selectExistingpicture]: unrecognized
selector