0

i'm pulling a 2 dimensional array from a remote server:

- (NSMutableArray*)qBlock{

NSURL *url = [NSURL URLWithString:@"http://wsome.php"];
NSError *error;
NSStringEncoding encoding;
NSString *response = [[NSString alloc] initWithContentsOfURL:url 
                                                usedEncoding:&encoding 
                                                       error:&error];
const char *convert = [response UTF8String];
NSString *responseString = [NSString stringWithUTF8String:convert];
NSMutableArray *sample = [responseString JSONValue];

return sample;
}

and putting them into:

NSMutableArray *qnBlock1 = [self qBlock];
NSString *answer1 = [NSString stringWithFormat:[[qnBlock1 objectAtIndex:0]objectAtIndex:1]];
answer = [[NSMutableDictionary alloc]init];
[answer setObject:answer1 forKey:@"1"];

question1.text = [[qnBlock1 objectAtIndex:0] objectAtIndex:0];
label1a.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:2];
label1b.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:3];
label1c.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:4];
label1d.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:5];

I received this error during runtime

-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6c179502012-04-30 09:43:50.794 AppName[371:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6c17950'

Is this due to syntax issue for 2 dimensional array?

Joe Shamuraq
  • 1,245
  • 3
  • 18
  • 32
  • You should show us at least a sample of the JSON you're processing (and also NSLog what you have at several steps along the way). You're assuming there's a dictionary inside two levels of NSArray, but the error is telling you that you're trying to treat a dictionary like an array. – Hot Licks Apr 30 '12 at 02:14

2 Answers2

3

You're not getting back a multi-dimensional array. You're getting back an array of NSDictionary objects. The error you got indicates that you're trying to send the message objectAtIndex: to an NSDictionary object, which fails since it has no such selector.


Update:

After chatting on the side, it became apparent that the following was true:

  1. The user was using the SBJson library to parse the return value from his php web service.
  2. The return value was either:
    • An NSDictionary with each key being the text representation of its (non-index-based) location in the list (@"1", @"2", etc...) and each value being an NSArray of NSString objects, or
    • An NSArray of NSString objects (seems to be the way a single "answer" returns)

Here's the code I supplied to let him iterate through his return value:

NSURL *url = [NSURL URLWithString:@"{his url}"];
NSError *error;
NSStringEncoding encoding;
NSString *response = [[NSString alloc] initWithContentsOfURL:url usedEncoding:&encoding error:&error];
const char *convert = [response UTF8String];
NSString *responseString = [NSString stringWithUTF8String:convert];
NSLog(@"%@", responseString);
SBJsonParser *parser = [[SBJsonParser alloc] init];
id sample = [parser objectWithString:responseString];
if ([sample isKindOfClass:[NSDictionary class]]) {
    for (id item in sample) {
        NSLog(@"%@", [item description]);
        NSArray *subArray = [sample objectForKey:item]; // b/c I know it's an array
        for (NSString *str in subArray) {
            NSLog(@"item: %@", str);
        }
    }
} else if ([sample isKindOfClass:[NSArray class]]) {
    for (NSString *str in sample) {
        NSLog(@"item: %@", str);
    }
}

Hope it helps, J!

mbm29414
  • 11,558
  • 6
  • 56
  • 87
  • originally it was 1 dimensional array and it worked. But i dun want to waste on number of times it needs to connect just to get 5 sets of data... so i decided to make the server side 2-dimensional array... – Joe Shamuraq Apr 30 '12 at 01:59
  • That's fine, but however the data comes in, you're actually getting back an NSArray/NSMutableArray populated with NSDictionary objects, **not** sub-arrays. You might not intend that, but the error message you've got indicates that's the case. You might try interrogating the NSDictionary objects you are getting to see if you can easily get what you want without re-writing (again!) your web service. – mbm29414 Apr 30 '12 at 02:05
  • This is only for testing, so it's not recommended for the final application. Try this: `for (id key in (NSDictionary *)[qnBlock1 objectAtIndex:0]) { NSLog(@"%@", [dic objectForKey:key]); }` – mbm29414 Apr 30 '12 at 02:10
  • Sorry, I didn't quite edit all of my code... `dic` was the NSDictionary's name in my example. Change `dic` to `qnBlock1`. – mbm29414 Apr 30 '12 at 02:18
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/10678/discussion-between-teamstar-and-mbm30075) – Joe Shamuraq Apr 30 '12 at 02:22
  • Seems to me whoever is serving that JSON doesn't understand it very well -- it's exactly backwards of what makes sense. – Hot Licks Apr 30 '12 at 10:49
  • @HotLicks I'm not sure that's the case. The JSON string seems to be formatted in a little bit of a weird way. I'm no JSON expert, but looking at the original string, it ***kind of*** makes sense. Unless, of course, you're talking about the web service, in which case I might agree with you :-). – mbm29414 Apr 30 '12 at 11:48
  • @mbm30075 -- It's apparently coming from a web service. The "normal" way would be to have each group of items in a dictionary (since the items have different meanings), and then, if there is more than one group, put the groups into an array (since the groups are all identical in topology/meaning). The web service is providing exactly the opposite. – Hot Licks Apr 30 '12 at 12:08
  • @HotLicks -- I'm not sure whether it matters, but the web service ***appears*** to be returning groups of strings, "grouped" as an array. When more than 1 group is returned, each group is assigned to a dictionary with its key being the string representation of its position (1st group is "1", 2nd is "2", etc.). So, my point is that, based on the actual string I saw (before it went to the JSONParser), I think the JSON engine might be making good decisions. It seems to me that the "tweaks" to make (if any) would be in the web service. Thanks! – mbm29414 Apr 30 '12 at 12:12
  • @mbm30075 -- The JSON parser has no decisions to make. It's the JSON source -- "the original string" -- that's that being SERVED by the web server that's bass-ackwards and doesn't make sense. – Hot Licks Apr 30 '12 at 15:06
  • @mbm30075 - tweak to web service? As in tweak the arrays from server? – Joe Shamuraq May 02 '12 at 00:22
  • @TeamStar Yeah. It seems like you're using php, which isn't what I use, but if I'm writing a .NET web service (what I *actually* use) and was returning data like you are, I have some control over the output. For instance, do you know why your data structure is different when you're returning 1 array vs. more than 1? Perhaps you can write some code into the web service to standardize its output, making it more friendly when converting into/out of JSON. Does that help? – mbm29414 May 02 '12 at 11:49
  • @mbm30075 - Thanx. I will look into it. In the meantime, while resolving this issue, i'm just connecting 5 times as initially done but adding UIAlertView for the loading process. I bumped into the AlertView not showing. Here's the [link](http://stackoverflow.com/questions/10430606/inserting-alert-view-but-not-functioning) i posted to... – Joe Shamuraq May 03 '12 at 11:49
1

I think from your error message, you're sending objectAtIndex to a dictionary. NSDictionary doesn't have such a method. You should use objectForKey instead.

Kaan Dedeoglu
  • 14,765
  • 5
  • 40
  • 41
  • i converted the the 'answer' part into NSString before inserting it into NSMutableDictionary... i didn't insert it directly... – Joe Shamuraq Apr 30 '12 at 01:56
  • I would just set breakpoints before the lines NSString *answer1 = [NSString stringWithFormat:[[qnBlock1 objectAtIndex:0]objectAtIndex:1]]; and then 1.text = [[qnBlock1 objectAtIndex:0] objectAtIndex:0]; to see which line actually causes the crash, and go on from there – Kaan Dedeoglu Apr 30 '12 at 01:58
  • 1
    @Kaan -- Or simply look at the line reported in the exception traceback. – Hot Licks Apr 30 '12 at 02:19