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
Related
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";
}
I have made a custom delegate:
Example.h:
#protocol DismissExamplePopoverDelegate
- (void) dismissExamplePopover;
- (int) getUserID;
#end
#interface Example : UIViewController{
id<DismissExamplePopoverDelegate> delegate;
}
#property (nonatomic, assign) id<DismissExamplePopoverDelegate> delegate;
It is called in Example.m like follows:
[[self delegate] getUserID];
In my maincontroller.h:
#import "Example.h"
#interface MainScreen : UIViewController<DismissExamplePopoverDelegate>
maincontroller.m:
-(int) getUserID
{
return 100;
}
the view Example is called by the following method:
ExampleController = [[Example alloc] initWithNibName:#"Example" bundle:nil];
ExamplePopoverController = [[UIPopoverController alloc] initWithContentViewController:ExampleController];
[ExampleController setDelegate:self];
ExamplePopoverController.popoverContentSize = CGSizeMake(600, 480);
if ([ExamplePopoverController isPopoverVisible]) {
[ExamplePopoverController dismissPopoverAnimated:YES];
} else {
CGRect popRect = CGRectMake((self.EditExampleSelectAddButtonProperty.frame.origin.x),
(self.EditExampleSelectAddButtonProperty.frame.origin.y),
(self.ExampleSelectAddButtonProperty.frame.size.width),
(self.ExampleSelectAddButtonProperty.frame.size.height));
[ExamplePopoverController presentPopoverFromRect:popRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
If I place [[self delegate] getUserID] in any function other than viewdidload it works perfectly: returns 100; in viewdidload it returns 0.
What i want to achieve is a delegate to be called automatically when the popover loads. Is viewdidload the best place for it, or is there somewhere else
A couple of people have said this, but haven't been clear enough about the solution.
Instead of doing this:
ExampleController = [[Example alloc] initWithNibName:#"Example" bundle:nil];
ExamplePopoverController = [[UIPopoverController alloc] initWithContentViewController:ExampleController];
[ExampleController setDelegate:self];
Do this:
ExampleController = [[Example alloc] initWithNibName:#"Example" bundle:nil];
[ExampleController setDelegate:self];
ExamplePopoverController = [[UIPopoverController alloc] initWithContentViewController:ExampleController];
What's happening is that -[UIPopoverController initWithContentViewController:] uses its contentViewController's view, causing -[Example viewDidLoad] to be called. Since you haven't yet set the delegate at that point, the delegate is nil, and attempting to call any method on nil returns nil, 0, or 0.0.
Make sure you're actually assigning the delegate property to MainController. For instance, wherever you've initialized Example, you need to set the delegate property:
Example *example = [[Example alloc] init];
example.delegate = self; // Use this if you're initializing Example in MainController
If you're not initializing Example in MainController, instead of "self" use the MainController instance.
In Example.m you need to add line:
[self setDelegate:delegate];
Also, you need to #synthesize delegate;
Hope it help)
I've subclassed UIImageView, it's called ACCascadeImageView.
#interface ACCascadeImageView : UIImageView{
BOOL isSpotlight;
}
#property (assign, nonatomic) BOOL isSpotlight;
-----
#implementation ACCascadeImageView
#synthesize isSpotlight;
I then create instances like so, and add a gesturerecognizer..
ACCascadeImageView *imageview =
[[ACCascadeImageView alloc] initWithFrame:imageframe];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[imageview addGestureRecognizer:singleTap];
In the handleSingleTap method, I loop through my UIScollView subviews, and I try to do this for each one...
(imageview in this scope is [gestureRecognizer view])
[imageview setIsSpotlight:NO];
But I get this...
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[UIImageView setIsSpotlight:]: unrecognized selector sent to instance 0x6888be0'
Why has my ACCascadeImageView suddenly become UIImageView? I apologize if I'm doing something stupid, but I've subclassed UIImageView before just fine. I'm confused.
I should say that I've NSLog'd [imageview class] and I get, "ACCascadeImageView".
Here's the problem:
NSArray *cascadeImages = [PhotoCascade subviews];
for (ACCascadeImageView *v in cascadeImages){
NSLog(#"RESPONDS: %d", [v respondsToSelector:#selector(setIsSpotlight:)]);
[v setIsSpotlight:NO];
}
I get :
RESPONDS: 1
RESPONDS: 0
Then it dies.
You can't be sure [gestureRecognizer view] is your UIImageView. To check this try NSLog(#"view: %#", [gestureRecognizer.view class]);. My tests says it's just UIView.
If you're adding gesture recognizer to your image view the selector will be fired only when the user taps this view. So you could omit those checks at all.
By your results, and since you only test once per object, it seems the first object in the array is your custom subview, but the second is not. Maybe somehow one of the objects in cascadeImages isn't an ACCascadeImageView. Step through the array and perform introspection on each one, logging the results, to make sure the array only contains ACCascadeImageViews.
You're saying that your handleSingleTap is returning TRUE in response to respondsToSelector:#selector(setIsSpotlight:), but then when you try to use setIsSpotlight, it fails? That is a mystery.
For example, I've created this super simple example, and it works as you'd expect:
#import "ViewController.h"
#interface Test : UIImageView
#property (assign, nonatomic) BOOL isSpotlight;
#end
#implementation Test
#synthesize isSpotlight;
#end
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
Test *test = [[Test alloc] initWithFrame:self.view.frame];
[self.view addSubview:test];
test.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[test addGestureRecognizer:tap];
}
- (void)handleSingleTap:(UIGestureRecognizer *)sender
{
Test *imageview = (Test *)[sender view];
NSLog(#"%s %d", __FUNCTION__, [imageview respondsToSelector:#selector(setIsSpotlight:)]);
[imageview setIsSpotlight:NO];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
The problem has to be something simple, but with limited code snippets provided in your question, it's not obvious what the problem is. But the code you've provided above would not manifest the sort of problem you describe. There must be some rogue UIImageView in your app!
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];
}
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];