3

I'm trying to create programmatically a uiPickerView and add it to a view without using interface builder. Don't get me wrong, I like IB but the reason why I want to do it this way is because i'm trying to build an object that I can quickly plug in to produce popup menus using UIPopoverViewController and a variety of different subViews (such as uiPickerView) as the menu in the popup. I've already made this work by building the menu in IB and initializing the popup with its ViewController so I know how this works for the most part.

I've entered the relevant code below and this is the two errors I get when I run it: - "Could not find mapped image UIPickerViewFrameRight-162-Popover.png" - "Could not find mapped image UIPickerViewFrameLeft-162-Popover.png"

I don't know what these images are but I'm assuming they are the png's of the picker view.

menu = [[UIPickerView alloc]initWithFrame:CGRectMake(0,100,162,162)];
  menu.delegate = self;
  menu.dataSource = self;

  [menu reloadAllComponents];
  [menu selectRow:0 inComponent:0 animated:YES];

  //Add the picker to the view
  [customViewController.view addSubview:menu];

  popView = [[UIPopoverController alloc] initWithContentViewController:customViewController] ;
  [popView setDelegate:self];
  CGRect pos = [rootView frame];
  [popView presentPopoverFromRect:CGRectMake(pos.origin.x,pos.origin.y,0,pos.size.height) 
         inView:displayView permittedArrowDirections:arrowDir animated:YES];

Now this Code will crash the program unless you remove the line where I try to add the picker to the view, at which point I just get the blank popover. So I know that it is the picker that is causing this issue however I don't know how to fix it. I've been searching all day but every tutorial online on uipickers all include using IB. My guess is that this is a really stupid error like missing an import or something but if anyone can tell me what I'm doing wrong it would be greatly appreciated.

Also note that I followed the tutorials on how to set up the dataSource and delegate methods for the UIPickerView and I'm pretty sure they are fine however if you want to verify here you are: Thanks again.

#import "PopUpMenuViewController.h"



@implementation PopUpMenuViewController

@synthesize menuType;
@synthesize data;
@synthesize popView;
@synthesize menu;
@synthesize customViewController;

#pragma mark -
#pragma mark UIPOPOVERCONTROLLER DELEGATE METHODS
#pragma mark -

- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{

 //Delegate this too the User of this class
 return TRUE;
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController{

 //Delegate this too the User of this class
}

#pragma mark -
#pragma mark CUSTOM POPOVERVIEWCONTROLLER METHODS
#pragma mark -

-(void) initWithMenuType:(int)type{

 menuType = type;
}

-(id) initWithMenuType:(int)type andData:(NSMutableArray *)dataSet fromViewItem:(id)sender 
    withMainView:(UIView *)mView{

 [super init];
 menuType = type;
 data = dataSet;
 rootView = sender;
 displayView = mView;
 arrowDir = UIPopoverArrowDirectionUp;
 customViewController = [[UIViewController alloc] initWithNibName:@"PopUpMenu" bundle:nil];

 return self;
}

-(void) setPopUpArrowDirection:(UIPopoverArrowDirection) arrow{

 arrowDir = arrow; 
}


-(void) showPopUp{ 

 //UIPicker Menu
 if (menuType==1) {

  //UIPicker Setup
  menu = [[UIPickerView alloc]initWithFrame:CGRectMake(0,100,162,162)];
  menu.delegate = self;
  menu.dataSource = self;

  [menu reloadAllComponents];
  [menu selectRow:0 inComponent:0 animated:YES];

  //Add the picker to the view
  [customViewController.view addSubview:menu];

  popView = [[UIPopoverController alloc] initWithContentViewController:customViewController] ;
  [popView setDelegate:self];
  CGRect pos = [rootView frame];
  [popView presentPopoverFromRect:CGRectMake(pos.origin.x,pos.origin.y,0,pos.size.height) 
         inView:displayView permittedArrowDirections:arrowDir animated:YES];
  //[popView setPopoverContentSize:CGSizeMake(menu.frame.size.width+5,menu.frame.size.height+5)];

 }


}

#pragma mark -
#pragma mark VIEW CONTROLLER DELEGATE METHODS
#pragma mark -

// The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
 if (self) {
 // Custom initialization.
 }
 return self;
 }
 */

/*
 // Implement loadView to create a view hierarchy programmatically, without using a nib.
 - (void)loadView {
 }
 */

/*
 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
 - (void)viewDidLoad {
 [super viewDidLoad];

 }*/

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    return YES;
}


- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc. that aren't in use.
}


- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [super dealloc];
 [data release];
 [popView release];
 [menu release];
 [rootView release];
 [displayView release];
 [customViewController release];

}

#pragma mark -
#pragma mark UIPICKERVIEW DELEGATE & DATASOURCE METHODS
#pragma mark -

#pragma mark -
#pragma mark UIPickerViewDataSource Methods

- (NSInteger) pickerView: (UIPickerView *) pickerView numberOfRowsInComponent: (NSInteger) component {

 return [data count];
}

- (NSInteger) numberOfComponentsInPickerView: (UIPickerView *) pickerView {

 return 1;
}

#pragma mark -
#pragma mark UIPickerViewDelegate Methods



// Row height in pixels
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {

 return 40.0f;
}

// Column width in pixels
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {

    return 90.0f;
}

- (NSString *) pickerView: (UIPickerView *) pickerView titleForRow: (NSInteger) row 
    forComponent: (NSInteger) component {

 return [data objectAtIndex:row];
}


- (void) pickerView: (UIPickerView *) pickerView 
    didSelectRow: (NSInteger) row inComponent: (NSInteger) component {
}
RBI
  • 803
  • 2
  • 14
  • 25

3 Answers3

5

If anyone else encounters this particular warning in the console "Could not find mapped image UIPickerViewFrameRight-162-Popover.png", I think I've figured out why it appears.

The HIG indicates loosely that UIPickerView should only be added to a Popover on the iPad.

"On iPad, present a date and time picker only within a popover."

http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/UIElementGuidelines/UIElementGuidelines.html

In my experiments, the UIPickerView must be the direct and only view of the current UIViewController in a popover. If the UIPickerView appears elsewhere in a view hierarchy, the warning appears and the UIPickerView will look bad (like it's missing the left and right portions of the view).

In the code above, you can see that the UIPickerView was added as a subview of the rootView in the customController:

[customViewController.view addSubview:menu];

This probably would have worked if the UIPickerView was the root view in the customController.

You can programmatically make the UIPickerView the root view of the controller by overriding the loadView method of the controller and assigning the UIPickerView directly to the root view of the controller:

- (void)loadView {
  CGRect frame = CGRectMake(0,0, 300, 300);
  UIPickerView *v = [[[UIPickerView alloc] initWithFrame:frame] autorelease];
  v.delegate = self;   // assuming controller adopts UIPickerViewDelegate 
  v.dataSource = self; // assuming controller adopts UIPickerViewDataSource 

  self.view = v;
}

Hope this helps someone.

Pat
  • 814
  • 8
  • 9
2

Alright well I'm not quite sure what happened but I deleted the project and re-wrote this code and voila... No more issues.

RBI
  • 803
  • 2
  • 14
  • 25
0

I just recently ran into the same issue with my app on the iPad and iPhone. It actually was a simple but stupid fix which involved making the height on the iPad to 180 and 162 on the iPhone. God must love apple s/w but I don't.

bool.dev
  • 17,508
  • 5
  • 69
  • 93