Search code examples
objective-cuipickerviewuidatepickerxcode8

UIPickerView & DatePicker behaving abnormally


I am converting a project from springs and struts to storyBoard. There's a VC in which after login, the user has to initialize profile info. I have four fields by name, dob, gender and city. On gender and dob I've implemented pickerView and DateView respectively so on tapping the text field picker/date View are presented so that user can select from them. I've pinned them from the bottom of my screen and haven't hidden them in the storyboard attribute's inspector. It's being done manually in the code.

On testing, i am having some trouble as datePicker is behaving abnormally and if tapped anywhere else it comes up and the pickerView is also not selecting the option on the done button action. pickerView's delegate and data source are connected. It was working perfectly fine with the same code in springs and struts. I want to know what possibly could I be doing wrong here and if there's an easy way to hide unhide the views with my desired output.

This is the showDatePickerView method

-(void) showDatePickerView {

if (self.dob != nil) {
    [self.datePickerView setDate:self.dob];
}

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.50];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.datePickerView.backgroundColor = [UIColor groupTableViewBackgroundColor];

CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
//Origin will be screen size - picker height
float origin = iOSDeviceScreenSize.height - 256;
CGRect frame = self.datePickerView.frame;
frame.origin.y = origin;
self.datePickerView.frame = frame;
frame = self.toolBar.frame;
frame.origin.y = origin-44;
self.toolBar.frame = frame;

[UIView commitAnimations];
}

This is the hideDatePickerViewMethod

-(void) hideDatePickerView {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.50];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;

CGRect frame = self.datePickerView.frame;
frame.origin.y = iOSDeviceScreenSize.height;
self.datePickerView.frame = frame;
frame = self.toolBar.frame;
frame.origin.y = iOSDeviceScreenSize.height;
self.toolBar.frame = frame;
[self.view setUserInteractionEnabled:YES];
[UIView commitAnimations];
}

Like this i've also implemented show pickerView and hide pickerView methods which are called in the delegate method of textField "textFieldShouldBeginEditing"


Solution

  • Let me tell you a different and easy approach for this type of situation:

    Create on pickerView in the interface like this:

    UIPickerView *pickerView;
    UITextField  *activeTextField; //To keep the reference of activeTextField
    

    Then in the ViewDidLoad() write:

    pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 200)];
    pickerView.dataSource = self;
    pickerView.delegate = self;
    

    Now you have initialized your pickerView

    Here comes the UIPickerViewDataSource and UIPickerViewDelegate methods:

    - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
    {
        return 2; //Whatever number of Components you want
    }
    
    
    - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent :(NSInteger)component {
    
        if (component==0)
        {
            return [YOUR_ARRAY count];
        }
        else
        {
            return [YOUR_ARRAY count];
        }
    }
    
    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    
    //You can even update your UITextfield if you want or whatever the UIElement you want to update
        //UITextField* nextTextField;
    
         //if (activeTextField.tag == 301) {
    
         //} else if(activeTextField.tag == 302)  {
    
       //}
    }
    
    
    
    - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
    {
    
        switch (component)
        {
            case 0:
                return [YOUR_ARRAY objectAtIndex:row];
                break;
            case 1:
                return [YOUR_ARRAY objectAtIndex:row];
                break;
    
        }
        return nil;
    }
    

    Now in the textFieldShouldBeginEditing write:

    - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {       // return NO to disallow editing. {
    
    activeTextField=textField;
    //Now check for which textField you want to show pickerView
    if activeTextField == YOUR_TEXTFIELD {
    
    textField.inputView=pickerView;
     }
    }
    

    Let me know if you found any difficulty or any extra functionality you want!