Search code examples
iosuitextfielduipickerviewuitoolbaruiactionsheet

UIPickerView with toolbar when UITextField is clicked


I'm trying to get a UIPickerView to display when a UITextField is clicked on by the user. I also want the UIPickerView to have a toolbar at the top with buttons to submit the selection and cancel.

Do I need to connect a UIPickerView in the interface builder, or connect an action somewhere else? I am also getting warnings when I build. One warning is under the resignFirstResponder. It says:

local declaration of age hides instance variable

There are several more warning similar to the one above for different variables.

Another warning is:

Class 'PracticePickerViewController' does not implement the 'UIActionsheetDelegate' protocol.

Here are my .h and .m files:

.h

#import <UIKit/UIKit.h>

@interface PracticePickerViewController : UIViewController <UITextFieldDelegate>{

    IBOutlet UITextField *age;
    IBOutlet UIPickerView *agePickerView;
    IBOutlet UIActionSheet *actionSheet;
    IBOutlet UIToolbar *pickerToolbar;

}


@end

.m

#import "PracticePickerViewController.h"

@implementation PracticePickerViewController

-(void)textFieldDidBeginEditing:(UITextField *)age{
    [age resignFirstResponder];

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

    [actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
    CGRect pickerFrame = CGRectMake(0,40,0,0);

    UIPickerView *agePickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
    agePickerView.showsSelectionIndicator = YES;
    agePickerView.dataSource = self;
    agePickerView.delegate = self;
    [actionSheet addSubview:agePickerView];

    pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0,0,320,44)];
    pickerToolbar.barStyle = UIBarStyleBlackOpaque;
    [pickerToolbar sizeToFit];

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

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

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

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

    [pickerToolbar setItems:barItems animated:YES];

    [actionSheet addSubview:pickerToolbar];
    [actionSheet addSubview:agePickerView];
    [actionSheet showInView:self.view];
    [actionSheet setBounds:CGRectMake(0,0,320,485)];

}

Solution

  • local declaration of age hides instance variable

    This means you've defined a variable name that is already used by a class variable (so in this case, you may have declared UITextField *age somewhere in the class, but you can't re-use variable name age in this class because the compiler will confuse it with the class variable).

    Class 'PracticePickerViewController' does not implement the 'UIActionsheetDelegate' protocol.

    You haven't made your PracticePickerViewController a UIActionsheetDelegate. To do this, you have change your interface header (PracticePickerViewController.h) to read:

    @interface PracticePickerViewController : UIViewController <UITextFieldDelegate, UIActionsheetDelegate>{
    

    Don't forget to implement the required delegate methods as well!

    Finally, I strongly recommend you check out the ActionSheetPicker project.
    It's a drop-in class that has exactly the functionality you're trying to implement, so you can either replace your current code with that, or just use it as a reference to see how to implement the embedded ActionSheet inside the UIPickerView correctly. Hope all that helps!