Search code examples
iosobjective-cuipickerview

Build error: Assigning to 'id<UIPickerViewDataSource>' from incompatible type 'NSArray *'


I have a UIPickerView that I am trying to set the datasource for; once the datasource is set, I place it into a modal popover to be displayed. Here is the code - manicuristArray is defined as NSArray, pvManicurist is the UIPickerView, all of the delegates for UIPickerView have been set correctly, as per samples I have found on SO):

    -(void) showModalManicurist:(int)tag {

    UIViewController* popoverContent = [[UIViewController alloc] init];

    UIView *popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 216)];
    popoverView.backgroundColor = [UIColor redColor];
    popoverContent.contentSizeForViewInPopover = CGSizeMake(300.0, 216.0);

    //  define the UIPickerView
    pvManicurist.frame = CGRectMake(0, 0, 300, 216);

    //  fill the names from the d/b into manicuristArray
    PreferenceData *pv = [PreferenceData MR_findFirst];  //  (everything is in one record)
    NSLog(@"pv.aStaffPos1: %@", pv.aStaffPos1);

    if(pv)  {   //  fill the UIPickerView
        self.manicuristArray = [[NSArray alloc] initWithObjects: pv.aStaffPos1, pv.aStaffPos2, pv.aStaffPos3, pv.aStaffPos4, pv.aStaffPos5,
                           pv.aStaffPos6, nil];
        NSLog(@"\nmanicuristArray.count: %d",manicuristArray.count);

        pvManicurist.dataSource = self.manicuristArray;        [pvManicurist reloadAllComponents];

     }

    //  add it to the popover
    [popoverView addSubview:pvManicurist];
    popoverContent.view = popoverView;
    popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
    popoverController.delegate = (id)self;
    [popoverController setPopoverContentSize:CGSizeMake(300, 216) animated:NO];

    //  show it below the staff name textbox
    [popoverController presentPopoverFromRect:boStaff.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp
                                     animated:YES];
}

The problem is I am getting this build warning:

Build error: Assigning to 'id' from incompatible type 'NSArray *'

which I believe is causing the UIPicker view not to be put into the UIPopover. I have several other popovers, all with UIDatePickers in them, and they work fine. I have looked on SO and Google and found nothing that answers this particular question, which is: why is this not working? and how do I fix the build error?

UPDATE: here are the delegate methods for UIPickerView:

//--  sets number of columns
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pvManicurist  {

    return 1; // One column
}

//--  sets count of manicuristArray
-(NSInteger)pickerView:(UIPickerView *)pvManicurist numberOfRowsInComponent:(NSInteger)component  {

    return manicuristArray.count;  //set number of rows
}

//--  sets the component with the values of the manicuristArray
-(NSString *)pickerView:(UIPickerView *)pvManicurist titleForRow:(NSInteger)row forComponent:(NSInteger)component  {

    return [manicuristArray objectAtIndex:row];  //set item per row
}

And here is the interface from the .h file:

@interface AppointmentsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UINavigationControllerDelegate, UIActionSheetDelegate, UITextFieldDelegate,UIPickerViewDelegate, UIPickerViewDataSource  >  {

Solution

  • You cannot assign an array as a data source for a data picker, because arrays do not provide the information the picker needs. In order to work correctly, the picker needs answers to at least these three questions:

    • How many components a picker should have,
    • How many rows each component has, and
    • What data to put in each row of each component.

    The data source answers the first two questions by implementing the data source protocol: you need

    - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
    

    to return the number of components, and

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

    to return the number of rows in a given component. Implement both methods in your class, and then assign

    pvManicurist.dataSource = self;
    

    Of course you need to implement methods of the delegate as well, but since you assign popoverController.delegate = (id)self; chances are that you have done that already.