Search code examples
iosobjective-cuipickerviewuitoolbar

Dynamically created UIBarButtonItem doesn't trigger on tap


I've got a UIPickerView that has a UIToolbar attached to it on the parent view's load with this code:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.itemSortPicker.hidden = false;

    pickerData = @[@"Name",@"Item Level",@"Crafting Level",@"Profit",@"Profit Percentage",@"Sell Price",@"Buy Price",@"Supply",@"Demand",@"Rarity"];

    self.itemSortPicker.dataSource = self;
    self.itemSortPicker.delegate = self;


    UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];

    pickerToolbar.barStyle = UIBarStyleDefault;
    [pickerToolbar sizeToFit];

    [pickerToolbar setFrame:CGRectMake(0, -pickerToolbar.bounds.size.height, 320, 44)];

    NSMutableArray *barItems = [[NSMutableArray alloc] init];


    UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(pickerCancel)];
    [barItems addObject:cancelBtn];

    UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
    [barItems addObject:flexSpace];

    UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(pickerDone)];
    [barItems addObject:doneBtn];

    [pickerToolbar setItems:barItems animated:YES];

    CGRect pickerRect = self.itemSortPicker.bounds;
    self.itemSortPicker.bounds = pickerRect;
    self.itemSortPicker.frame = CGRectMake(0, 44, 320, 216);

    [self.itemSortPicker addSubview:pickerToolbar];

}

Now the problem is, when I tap on either the 'done' or 'cancel' buttons, the associated method doesn't trigger. The method doesn't take any parameters and just does an NSLog action. The PickerView isn't taking focus from the bar because when I tap and drag on the buttons, the PickerView doesn't change.


Solution

  • The problem is that the UIToolbar isn't entirely inside the frame of the UIPickerView. As your code is written, although UIToolbar is a subview of UIPickerView, the toolbar is -pickerToolbar.bounds.size.height above the UIPickerView:

    [pickerToolbar setFrame:CGRectMake(0, -pickerToolbar.bounds.size.height, 320, 44)];
    

    so you're unable to interact with its buttons because it's hanging off the edge of its superview's frame. For example, if you changed the pickerToolbar frame like so:

    [pickerToolbar setFrame:CGRectMake(0, 0, 320, 44)];
    

    you should be able to interact with it.

    If you need this specific placement -pickerToolbar.bounds.size.height above the UIPickerView though, I suggest not adding it as a subview to UIPickerView and placing it appropriately as a subview to UIPickerView's superview instead. In general, if you need to interact with a subview it needs to be entirely within its superview's frame.

    Edit: In this case, if you're going to instead add the toolbar to the superview, like so:

    [self.view addSubview:pickerToolbar];
    

    I suggest trying out this frame to maintain your original placement:

    [pickerToolbar setFrame:CGRectMake(self.itemSortPicker.frame.origin.x, self.itemSortPicker.frame.origin.y - pickerToolbar.bounds.size.height, 320, 44)];
    

    (To calculate this new frame, I've added the UIPicker's x and y origin values to the frame's x and y to adjust for the change in the view's coordinate system.)