uitableviewuipickerviewdatasource

Managing UIPickerView datasource between a UIVIewController, a custom UITableViewCell and a Utility Class


I have a custom UITableViewCell class that contains a Picker. The cell and it's contents are populated by a core data entity. Since this custom cell will be viewable in more than one view controller, I have a utility class that I want to have to handle the construction, datasource and delegate methods.

I seem to be missing something as when I set the datasource to self, the cell displays properly. When I set it to the Utility class, only the numberOfComponentsInPickerView: method gets called and then the app crashes with nothing in the log except (lldb). For my code sample, I'm going to create a simple picker with one component and one row with the title "Test".

ViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    PickerCell *pCell = nil;
    Picker *picker = [self.array objectAtIndex:indexPath.row];
    UtilityCustomCells *cellUtility = [[UtilityCustomCells alloc]init];
    pCell = [cellUtility createPickerCell:tableView withReuseIdentifier:kPickerCellRID andPicker:picker];
    pCell.picker.delegate = cellUtility;  //does not work
    pCell.picker.dataSource = cellUtility;  //does not work
    /* This works
    pCell.picker.delegate = self;
    pCell.picker.dataSource = self;
    */
    return pCell;
    }
}

and in

utilityCustomCells.h

#import "PickerCell.h"
#import "Picker.h"

@protocol CustomCellUtilityDelegate <NSObject,UIPickerViewDataSource,UIPickerViewDelegate>
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;

@end

finally:

UtilityCustomCells.m

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    NSLog(@"Here1");
    return 1;
}

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    NSLog(@"Here2");
    return 1;
}

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    NSLog(@"Here3");
    NSString *title = @"Test";
    return title;
}

Just to re-iterate, only "Here2" gets printed to the logs. Any advice would be much appreciated. Thanks in advance!


Solution

  • I was able to figure this out. I was instantiating the UtilityCustomCell class inside the cellForRowAtIndexPath datasource method in ViewController.m. In fact, I needed to make it an instance variable of ViewController.m and alloc/init in viewDidLoad. So now:

    ViewController.m
    @interface AssetFormVC ()
    {
        UtilityCustomCells *cellUtility;
    }
    
    @end
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        cellUtility = [[UtilityCustomCells alloc]init];
        cellUtility.pickerDataSource = [self configurePickerData];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        PickerCell *pCell = nil;
        Picker *picker = [self.array objectAtIndex:indexPath.row];
        pCell = [cellUtility createPickerCell:tableView withReuseIdentifier:kPickerCellRID andPicker:picker];
        pCell.picker.delegate = cellUtility; 
        pCell.picker.dataSource = cellUtility; 
        return pCell;
        }
    }
    

    I can now send the dictionary with the picker datasource to the cellUtility via a property in UtilityCustomCells.h

    @property (nonatomic,strong) NSDictionary *pickerDataSource;