NSInvalidArgumentException error. Not running under UIUserInterfaceIdiomPad - objective-c

Whilst I understand why im receiving an error
'', reason: '-[UIPopoverController initWithContentViewController:] called when not running under UIUserInterfaceIdiomPad.'
Rectifying it is becoming a bit tricky. My pop over is only required on the ipad and not on the iphone version. I omitted any code for the iphones if statement and still got a crash. . Presuming that I must call a view on iphone as well as its a universal app, I simply called the nib in the if iphone statement, and that didn't work either.
- (IBAction)popZs:(id)sender {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if ([popoverController isPopoverVisible]) {
[popoverController dismissPopoverAnimated:YES];
} else {
[self->popoverController setPopoverContentSize: CGSizeMake(601, 571)];
[popoverController presentPopoverFromRect:((UIButton *)sender).bounds
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
}
else {
/////using iPhone/////not sure how to handle this spart
zsTablePop *pop = [[zsTablePop alloc] init];
pop.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[pop presentModalViewController:pop animated:YES];
}
Keep getting same erorr even though im using if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
creation of pop over
.m
#import "ICCircuitDetails.h"
#import "zsTablePop.h" ///////////////pop over xib/////
#interface ICCircuitDetails ()
{
zsTablePop *controller;
UIPopoverController *popoverController;
}
///////more code/////////////
- (id)initWithCircuit:(Circuit *)circuit
{
self = [super initWithCertificate:circuit.distributionBoard.certificate];
if (self) {
self.circuit = circuit;
[[NSBundle mainBundle] loadNibNamed:#"ICCircuitDetails" owner:self options:nil];
self.view.contentSize = CGSizeMake(self.contentView.frame.size.width, self.contentView.frame.size.height);
///////////other code here/////////////////
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
controller = [[zsTablePop alloc] initWithNibName:#"zsTablePop" bundle:nil];
popoverController = [[UIPopoverController alloc] initWithContentViewController:controller];

Your error message says you try to instantiate a popover. The code only is about presenting it. You need to handle the instantiation as well.

Related

Use two different nib files for iPhone 4 and iPhone 5

Is there any way to detect what device the user is using, then using that information, make the application use a specific nib file?
Right now, the code that I have is
- (BOOL)application: (UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions{
if(isiPhone5){
self.RootViewController = #"RootViewController_iPhone5";
}
else{
self.RootViewController = #"RootViewController_iPhone4";
}
}
My other code for finding the device works and tells me what device the user is using, yet doesn't actually change the .xib file from RootViewController_iPhone4.xib to RootViewController_iPhone5.xib. Is there any way to do this?
I don't want to use auto layout, because I would like to have other custom things happen depending upon the device, such as different button names in the view controller if the device being used is an iPhone 4 verses an iPhone 5
Try this way..
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height ==568)
{
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPhone5" bundle:nil];
}
else
{
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPhone4" bundle:nil];
}
Updated Answer
check this...
Black Screen for screen detection
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (IS_IPHONE_5)
{
self = [super initWithNibName:#"YourViewController~iphone5" bundle:nil];
}
else
{
self = [super initWithNibName:#"YourViewController~iphone" bundle:nil];
}
return self;
}
Try something like this
You can achieve this by the following way
create a macro in App delegate so that it will be used through out the Project. It will be based on the screen height for the device.
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
Now you can test the condition for iphone 4 and iphone 5
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
if(IS_IPHONE_5){
self.window.RootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController_iPhone5" bundle:nil];
}
else
{
self.window.RootViewController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
}
}
}
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480)
{
// iPhone 4 Classic
//first always target 4 for better performance & practice.
}
if(result.height == 568)
{
// iPhone 5
}
}else {
//it's ipad
}

iOS: UIImagePickerController and ResignFirstResponder

I have an application that allows the user to select a photo from their camera roll, and display it in a UIImageView. But, after they tap on which image they would like to display, the camera roll's view does not disappear. So, I figured that I would need to simply call [sender resignFirstResponder];. But, this did not do the trick. I've been trying multiple things and doing searching around, but to no avail. I'm very new to Objective-C, so any help is much appreciated. Here is the code I'm working with:
(imgPicker is the UIImagePickerController.)
- (IBAction)grabImage(id)sender {
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
_popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
[_popover presentPopoverFromRect:self.imageView.bounds inView:self.imageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else {
[self presentModalViewController:imgPicker animated:YES];
}
[self.imgPicker resignFirstResponder];
}
And this may or may not be relevant to the issue:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
if (imageView.image == nil) {
imageView.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
return;
}
if (imageView2.image == nil) {
imageView2.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
return;
}
}
You need just this line to dismiss modal picker in your delegate method:
[picker dismissModalViewControllerAnimated:YES];
resignFirstResponder in this case is useless
Try
[self dismissModalViewControllerAnimated:YES];
As you want to dismiss only picker view and not parent view of picker
you just have to use:
[picker dismissModalViewControllerAnimated:YES];
and you are done.

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

Strange Error With UIPopoverController

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];

Using addSubView or presentModalViewController in a standard method with paramaters?

I'm trying to reuse code, I have some tutorial view controllers / views, which I would like to call from an action sheet. However, the calling views are different. Sometimes the tutorial view(s) would need to be added as a subview and sometimes they would be added to the navigation controller.
How can I expand my standard function to cater for these two different situations ?
You can see what I'm having to do instead, which means duplicate code :(
I have a class called which holds the standard code, I want to add calls to views here directly.
-(void)showHelpClickButtonAtIndex:(int)buttonIndex:(UIView *)vw {
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
// do nothing
} else if (buttonIndex == 0) {
NSLog(#"Tutorial here");
}
}
I use in one view like this ...
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
CommonUI *cui = [CommonUI alloc];
[cui showHelpClickButtonAtIndex:buttonIndex:self.view];
[cui release];
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
UIViewController *theController = [[HelpViewController alloc]
initWithNibName:#"HelpView"
bundle:nil onPage:HelpPageCalcBalance];
[self.navigationController.topViewController
presentModalViewController:theController animated:YES];
[theController release];
}
}
And is another view like this...
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
[cui showHelpClickButtonAtIndex:buttonIndex:self.view];
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
theController = [[HelpViewController alloc] initWithNibName:#"HelpView"
bundle:nil onPage:HelpPageGettingStarted];
[self.view addSubview:theController.view];
}
}
Maybe the actionSheets could share one same delegate that would be a root viewController or the appDelegate that would know what to do according to it's current state. Hence the same actionSheet method would be used in both case.
If you put your appDelegate which can always be reached as the actionSheetDelegate, you should be able to gain control on every way to present your view, either modally or not in any of your views + the window.
EDIT (re-Edited with your code): Maybe try this
MyAppDelegate.h:
#interface MyAppAppDelegate : NSObject <UIApplicationDelegate, UIActionSheetDelegate>
(...)
- (void) showHelp;
MyAppDelegate.m:
- (void) showHelp {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#""
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles: #"Tutorial", #"Help Pages", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[actionSheet showInView:window];
[actionSheet release];
}
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
UIViewController *theController = [HelpViewController alloc];
if ([[self lvc] superview] != nil) {
theController = [initWithNibName:#"HelpView"
bundle:nil
onPage:HelpPageGettingStarted];
[window addSubview:theController.view];
} else {
theController = [initWithNibName:#"HelpView"
bundle:nil
onPage:HelpPageCalcBalance];
UINavigationController * navController = [tabBarController selectedViewController];
[navController.topViewController presentModalViewController:theController animated:YES];
}
[theController release];
}
}
and in your viewControllers:
- (void)viewDidLoad {
[super viewDidLoad];
MyAppDelegate *delegate = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:delegate
action:#selector(showHelp)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *infoItem = [[UIBarButtonItem alloc] initWithCustomView:infoButton];
self.navigationItem.rightBarButtonItem = infoItem;
[infoItem release];
}
Didn't try it but it should work.