NWPickerField, a combo box for the iPhone.

I was working on a project and needed a way to pick an expiration date for credit card processing and wanted to use the same control for choosing a state. The solution I came up with is a read-only picker field that uses the UIPickerView for input instead of the keyboard.

The idea was to have something that looked like an edit control, since users know to click on it, but used a picker view instead of a keyboard for entry. So this control is a marriage of a UITextView subclass and a UIPickerView subclass.

I am releasing the class for all to use.  The code is hosted on github ready to be branched and used. If you use the control let me know.

To use the code its very simple:

  1. Add the
    NWPickerField

    ,

    NWPickerView

    ,

    String+NSArrayExtension,

    and

    downArrow.png

    sources into your project.

  2. Drag a UITextField onto a view in InterfaceBuilder.
  3. Change its class to the
    CWPickerField

    class.

  4. Implement the
    NWPickerFieldDelegate

    protocol, which mirrors the

    UIPickerViewDelegate

    .

  5. Set the format string for the field when the view is loaded.

The code can be

Picker shot 1

picker shot 2

24 comments to NWPickerField, a combo box for the iPhone.

  • Zhu

    Nice job! man.

  • Perfect! I have an app i’m working on that can definitely use this functionality. :)

  • pjc

    I have add the NWPickerField, to a form in an App,
    but when I saved or cancel the form,
    the NWPickerView don’t disappear…

    How can I easily dismiss the NWPickerView?

  • erwinwang

    pjc ,
    you can update NWPickerField.m (didmovetoWindow function)
    add (if self.window.tag == int ) before if (appWindow = nil) to control when it appear .

    dear Scott Andrew ,
    I have one question about how can i use valuechanged method of NWPickerField for update other NWPickerField.text , please kindly feel free if you have time to reply , thank you.

  • Scott Andrew

    erwinwang,

    what exactly do you want to do? Do you want to set another field based on what you have selected? You should be able to just set the text? Right now you can’t set the text of the field. You can, however, pick the row using:

    -(void) selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated

    This would select the row and and component and update the text. I don’t currently have a way to just set the string and have it figure out the full selection. Feel free to branch and add that feature it would be a great addition.

  • Dwaine Bailey

    Hi Scott,

    I was just wondering if it was possible to ever update the contents of the Picker?

    Say that I have two PickerFields, and what the user selects in one has to affect what they can select in the other…

    I’ve tried to find some kind of “reload data” method, but I can’t figure out how to do it.

    I also tried to create a PickerField programmatically (instead of using Interface Builder) and I can’t seem to do that either…

    Any hints?

    Dwaine

  • Chris

    please tell me the Html Code

    I`m not shure, that i`m on the right Way

    #combobox1 {
    position: absolute;
    height: 20px;
    color: black;
    font-size: 11;
    width: 197px;
    -webkit-border-image: url(“res/images/combobox_80.png”) 10 18 10 5 / 10 18 10 5 repeat stretch;
    font-family: Helvetica;
    left: 63px;
    z-index: 2;
    top: 156px;

  • karthik

    Hi scott,

    you did a great job for me too,..but

    i’m implementing your class files as that you mentioned step by step, but picker is not loading with plist, i do no were i am doing mistake, picker is popup with empty box,..

  • Scott Andrew

    karthik,

    Did you follow the example that was included? If you send me an email I could help. I believe I included a plist example.

  • Hi Scott,

    I don’t really understand what one commenter wrote in regards to dismissing the picker view. Resigning first responded on the field doesn’t seem to work like it does with keyboards.

    Thoughts?

  • Adam

    I am trying to use this code in my iPhone app that I am developing. I am pretty new to this stuff so I am not sure how to do step 4 (implementing the protocol which mirrors the delegate). Can someone please explain this step and maybe provide a snippet of code showing where and how I have to do this?

    Thanks!!

  • Adam

    Okay i figured out the implementation part. Now i need to know how to make the picker disapper. Also, how do i make a custom list for the pickerview?

    thanks!

  • I found one way to make the PickerView disappear, but you have to have a textbox on the same window. On the app view’s “Touch Down” event, you can make a textbox become first responder (which will make its keyboard appear) and then resign first responder (which will make it go away).

    Something like this:

    -(IBAction)backgroundTap:(id)sender {
    [txt becomeFirstResponder];
    [txt resignFirstResponder];
    }

  • Jocke

    Hi! Solved responder problem!

    Insert following method in NWPickerField.h:
    -(BOOL) resignFirstResponder;

    And implement in NWPickerField.m:

    -(BOOL) resignFirstResponder {
    [pickerView resignFirstResponder];
    return YES;
    }

    and then just call this method for example:
    // nwpf is an NWPickerField
    [nwpf resignFirstResponder];

  • Scott Andrew

    Jocke,

    Thats a good point. I thought i had added support for that. Can you push your change to git?

    Sorry i have been MIA lately. Multiple jobs have had me busy.

  • Hi Scott

    Thanks for this implementation. It was almost exactly what I needed. One thing I did want was the ability to dismiss the picker without having to click on another field in the view. What I wound up doing was overriding the hit test event to store the target view. Then in the touch event I close out the picker when the touch count is 1. Effectively this causes the picker to toggle when you tap on one of the choices. Personally I like this behavior better.

    I am relatively new to iphone so not sure how blessed this approach is but I am inclined to think you can get away with it given the message loop is single threaded. Hopefully this is useful to someone.

    So in NWPickerView I add a member
    UIView* eventView and a corresponding property to be released in dealloc.

    And add the following source. to NWPickerView.m

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
    NSLog(@”hitTest”);
    UIView* hitView = [super hitTest:point withEvent:event];
    if (nil == hitView) {
    return hitView;
    }

    self.eventView = hitView;
    return self;
    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
    NSLog(@”touchesBegan”);
    if (self != eventView) {
    [eventView touchesBegan:touches withEvent:event];
    }
    else {
    [super touchesBegan:touches withEvent:event];
    }
    }

    - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
    {
    NSLog(@”touchesCancelled”);
    if (self != eventView) {
    [eventView touchesCancelled:touches withEvent:event];
    }
    else {
    [super touchesCancelled:touches withEvent:event];
    }

    }

    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
    NSLog(@”touchesEnded”);

    if (eventView != self) {

    UITouch* touch = (UITouch*)[touches anyObject];
    [eventView touchesEnded:touches withEvent:event];

    if ([touch tapCount] == 1) {
    [self toggle];
    }

    }
    else {
    [super touchesEnded:touches withEvent:event];
    }

    }

    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
    NSLog(@”touchesMoved”);
    if (self != eventView) {
    [eventView touchesMoved:touches withEvent:event];
    }
    else {
    [super touchesMoved:touches withEvent:event];
    }

    }

  • We are working on some clients that need this kind of picker…in fact they need this picker in a souped-up mode with more features added. Our coders don’t get down to quite this deep a level of detail.

    So, who could take this code and modify it for us more? Scott or somebody out there looking for a project?

    :)

  • Dipak

    Hello

    I have one problem during implementing your code into my project.

    My project is based on tabbar controller so once user log in he will redirect to first tab of tabbar controller.

    Now on third tab of tabbar controller that is suppose associated to SearchViewController.xib i have put two fields for
    car and states and make proper outlet connection. I have also include required all the files under NWPICKERFIELD group.

    Still when i clikc on either car or states NWpicker field it comes up with black picker only no data come up as i have already created two plist file that is Cars.plist and States.plist

    Please help

  • Scott Andrew

    I would need to see sample code. Contact me offline.

  • Hi.
    This is a nice component, i’m testing it.
    But if in in your project i change state to an array like:
    states = [NSArray arrayWithObjects:@"--", @"one", @"two", @"three", nil];
    It shows error on compilation.
    And I like to know if the component is created by code, how can i assign the data?
    Thanks.

  • I’ve never been a big fan of Apple but I have to admit that the iphone is quite good! :) I’d like to know if this issue about the iphone 4 is important or not. I’d like to buy the new 4g and I was wondering if the calls actually drop more or not. Sorry if it’s a bit off topic :P Thanks a lot

  • Look… I think… there’s bug!!!!

    Only works the first commponent… Others don’t work…!!!

    Please… Help me….ㅠ.ㅜ

  • how can I add here DatePicker…

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>