2

I have a pickerview with which I would want to display values using JSON parsing. I am aware some questions on the site already tackle parsing and pickerview but mine is slightly different in regards to the structure of my json file. Here's a sample of the json file.

[
{
"model":"juice",
"id" :
  [
    {
        "version": "version01"
    },

    {
        "version": "version02"
    }

  ]
},
 {
"model":"cream",
"id" :
[
  {
      "version": "cream01"
  },

  {
      "version": "cream02"
  }
]
}
]

and my .m file

- (void)viewDidLoad
    {
    [super viewDidLoad];

    NSURL * serverhost = [NSURL URLWithString:@"http://my.json"];

    NSError *error;

    NSData  * Data  = [NSData  dataWithContentsOfURL: serverhost];

    self.modelsArray= [NSJSONSerialization JSONObjectWithData:Data   options:NSJSONReadingAllowFragments error:&error];

    NSLog(@"%@", modelsArray);
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component
{
    if (component == departments)
        return [self.modelsArray count];
    return [self.versionsArray count];
}


#pragma mark Picker Delegate Methods
- (NSString *)pickerView:(UIPickerView *)pickerView
         titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if (component == departments)
          return [[self.modelsArray    objectAtIndex:row]objectForKey:@"model"];
    return [[[self.versionsArray objectAtIndex:row]objectForKey:@"model"]objectForKey:@"version"];
}

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:    (NSInteger)component
{
    if (component == departments)
    {
        NSString * selectedRow = [[self.modelsArray objectAtIndex: row]    valueForKey:@"version"];
        NSArray * array = [sybreDepts objectForKey:selectedRow];
        self.
    }
}

@end

Basically when I select a model i.e juice or cream on the first column the second column should display its contents with key being 'versions' thus when juice is selected "version01" and "version02" should be displayed on the second column.

In regards to the line return [[[self.versionsArray objectAtIndex:row]objectForKey:@"model"]objectForKey:@"version"]; I don't believe it was executed correctly as I get an error

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xa18c450' . Any suggestions ? Thanks
7
  • Welcome to StackOverflow. A few comments to your question: The shown JSON is invalid; could it be that a double quote is missing after version02? What do you mean by "but the version names are not"? Does it crash? Doesn't it compile? Please better describe what you expect to happen and what happens actually. Commented Jan 2, 2013 at 11:57
  • Is the line return [[[self.versionsArray objectAtIndex:row]objectForKey:@"model"]objectForKey:@"version"]; ever called? If you retrieve the element with the key model, you just get a string. But your code expects to find a JSON object with a version key. Commented Jan 2, 2013 at 12:00
  • Hi Codo, thank you. I have corrected json file, just typographical errors. Basically when I select a model i.e juice or cream on the first column the second column should display its contents with key being 'versions' thus when juice is selected "version01" and "version02" should be displayed on the second column. In regards to the line return [[[self.versionsArray objectAtIndex:row]objectForKey:@"model"]objectForKey:@"version"];. Commented Jan 2, 2013 at 12:11
  • I don't believe it was executed correctly as I get an error *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xa18c450' Commented Jan 2, 2013 at 12:12
  • 1
    Now that's the important information you should have put in your question in the first place. Commented Jan 2, 2013 at 12:13

1 Answer 1

2

If you nicely indent your JSON data and look at it:

[
    {
        "model": "juice",
        "id" : [
            {
                "version": "version01"
            }, 
            {
                "version": "version02"
            }
        ]
    },
    ....

then you'll see that it has the following structure (from the outer to the inner elements):

  1. an array
  2. a object/dictionary with two keys: model and version
  3. a string for the key model and an object/dictionary for the key id
  4. (for the key id only) a string for the key version

So if you want to access the second version of the first model, you have to write something like this:

NSArray* versionsArray = [[self.modelsArray objectAtIndex:modelRow] objectForKey:@"id"];
NSString* versionName = [[versionArray objectAtIndex: versionRow] objectForKey:@"version"];

In your code, I can't see where self.versionArray is ever assigned a value. And as I've pointed out in my comment, the following line doesn't match the JSON data structure:

return [[[self.versionsArray objectAtIndex:row]objectForKey:@"model"]objectForKey:@"version"];

The part:

[[self.versionsArray objectAtIndex:row]objectForKey:@"model"]

will return a NSString instance. And if you then call objectForKey:@"version", you'll get the unrecognized selector sent error.

Update:

The changed code could look like this:

.h file:

NSInteger modelRow;

.m file:

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if (component == departments)
        return [self.modelsArray count];

    NSArray* versionsArray = [[self.modelsArray objectAtIndex:modelRow] objectForKey:@"id"];
    return [versionsArray  count];
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if (component == departments)
          return [[self.modelsArray objectAtIndex:row]objectForKey:@"model"];

    NSArray* versionsArray = [[self.modelsArray objectAtIndex:modelRow] objectForKey:@"id"];
    return [[versionsArray objectAtIndex:row] objectForKey:@"version"];
}

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:    (NSInteger)component
{
    if (component == departments)
    {
        modelRow = row;
        [pickerView reloadComponent:1];
    }
}

@end
Sign up to request clarification or add additional context in comments.

5 Comments

versionRow how to get the value of it ?
I don't follow, what is modelRow and versionRow ? how can I show you my code since it would be nice to reedit the question ?
modelRow and versionRow are the row numbers of the first and second spinning wheel. Depending on where you put the code, it's just the row parameter of the function. You might need to save the row parameter as modelRow (instance variable) if pickerView:didSelectRow:inComponent: is called for the left spinning wheel. Then if pickerView:titleForRow:forComponent: is called for the right spinning wheel, modelRow is modelRow and row is versionRow.
ahh i see, i defined them initially like so #define models 0 and #define versions 1 in my .h file. I still have errors in my code, I would like to show you my code but re-editing the entire question would be wrong. What do you suggest ?
hi did you receive the message ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.