Search code examples
iosparse-platformuipickerview

UIPickerView data from Parse objects


In my app I am showing a picker view to let the user select one object to populate a text field. When the user changes the picker row, the textfield should show the title of the picker row, but it doesn't happen always. This is the code to get the source objects from Parse:

PFQuery *query = [PFQuery queryWithClassName:@"menu_categories"];
[query whereKey:@"category_restaurant" equalTo:restauranteID];
[query orderByDescending:@"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (!error) {
        _pickerData = objects;

        for (int i =0; i< [objects count];i++)
        {

            NSString *textoactual = self.menu_item_category_textfield.text;
            if ([[[objects objectAtIndex:i] objectForKey:@"category_name"]
                 isEqualToString:textoactual])
            {
                [self.room_picker reloadAllComponents];
                [self.room_picker selectRow:i inComponent:0 animated:YES];
                break;

            }

        }

    }
    else {
        NSLog(@"error");
    }
} ];

I am using the for statement to make it possible that the picker row to be first shown is the same as the textfield content. That works fine. But later if the user changes the picker row, the row title name that should be shown as the textfield text doesn't change properly, sometimes it does, but sometimes it doesn't.

These are the implemented picker view delegate methods:

- (int)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;
}



// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return _pickerData.count;
}


- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    PFObject *object = _pickerData[row];

    self.menu_item_category_textfield.text = object[@"category_name"];
    return object[@"category_name"];



}


-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
      inComponent:(NSInteger)component
{



}

What should I change to obtain the desired behaviour, that means to show always the selected picker view row title as text in the textfield?

EDITED:

enter image description here enter image description here enter image description here


Solution

  • Since your doing the query in viewDidLoad that would be a good place to create the NSArray for your UIPickerView, this ensures its loaded in memory. My guess is by creating a new PFObject every time the titleForRow: gets called, something gets lost in translation.

    So force load your _pickerData into memory:

    -(void)viewDidLoad {
        PFQuery *query = [PFQuery queryWithClassName:@"menu_categories"];
        [query whereKey:@"category_restaurant" equalTo:restauranteID];
        [query orderByDescending:@"createdAt"];
        [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
            if (!error) {
                _pickerData = [objects valueForKey:@"category_name"];
    ....
    }
    

    Then all you have to do in titleForRow: :

    - (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
        return self.pickerData[row];
    }
    

    And when you select it thats when you should be doing the appending not in titleForRow:

    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 
         self.menu_item_category_textfield.text = self.pickerData[row];
    }