Search code examples
objective-ciosuitextfielduipickerviewuipicker

Animating Picker in + Done button + TextField updating


Hi Can anyone help me out with this, ive been looking at alot of the previous questions on this subject and they seem a little complicated. I want to setup a picker that animates in on the touch of a text field which has an IBOutlet called locationField.

I dont want to add the picker or toolbar and buttons in my story boards I would rather do it programatically.

So far I have:

- (void)viewDidLoad
{
 //populate picker arrays
 locationPickerArray = [[NSArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5", nil];


    actionSheet = [[UIActionSheet alloc] initWithTitle:@"" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];

    [actionSheet showInView:self.view];

    UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0,480,32)];
    [pickerToolbar sizeToFit];
    pickerToolbar.barStyle = UIBarStyleBlackTranslucent;

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

    UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonSystemItemCancel target:self action:@selector(cancel_clicked:)];
    [barItems addObject:cancelBtn];

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

    UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(done_clicked:)];

    [barItems addObject:doneBtn];
    [pickerToolbar setItems:barItems animated:YES];
    [actionSheet addSubview:pickerToolbar];

    UIPickerView *picker = [[UIPickerView alloc] init];
    picker.frame = CGRectMake(0, 44, 320, 216);
    picker.delegate  = self;
    picker.dataSource = self;
    picker.showsSelectionIndicator = YES;
    [actionSheet addSubview:picker];
}

-(void)done_clicked:(id)sender
{
    [actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}

-(void)cancel_clicked:(id)sender
{
    [actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}

I have a few questions about this, it crashes on:

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DetailsScreenViewController numberOfComponentsInPickerView:]: unrecognized selector sent to instance 0xb505be0'

What does this mean?

My final question is how can I populate this picker and assign it to popup when the iboutlet I created earlier is clicked (location field).

Thank you


Solution

  • The reason for your crash is that you've assigned an instance of DetailsScreenViewController to be the dataSource and delegate of a UIPickerView without actually implementing the methods for these protocols. The assignment takes place here:

    picker.delegate  = self;
    picker.dataSource = self;
    

    The specific crash is telling you that you haven't implemented numberOfComponentsInPickerView:, part of the UIPickerViewDataSource protocol. You should have gotten a compiler warning about this actually. Learning to use those warnings can be really helpful! Anyways, to fix it, provide implementations for all of the required methods on both protocols. The details of the implementations will depend on the needs for your app. If you still need help with details let me know.

    Regarding your second question, I guess putting a UIPickerView inside a UIActionSheet is a thing now. I've never had a need to do it before, but here is a SO question with a lot of sample code for some background, not sure if you've read that one yet. But I think you'd just want to wait for the time you actually want to show the picker to call

    [actionSheet showInView:self.view];
    

    I think you can do this in a UITextFieldDelegate method, there are probably other ways. I'm going to try to do some experiments with that later and update this post.

    EDIT: If you assign your view controller as the delegate of whatever text field you're interested in, then you can implement this UITextFieldDelegate method:

    - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
    {
        [actionSheet showInView:self.view];
        return NO;
    }
    

    END EDIT

    Hope this helps, and let me know if you have any questions.