arcade16 arcade16 - 6 months ago 27
Objective-C Question

Unable to perform operations on response object?

I am struggling with a response object from one of my API calls. I receive it fine, but if I try to perform a count or valueForKey operation on the object, I get a "Unrecognized selector sent to instance" error. I have a feeling I am not correctly decoding the response object, any input would be greatly appreciated!

Method for the API call:

- (void)callRegisterAccount:(NSString *)email
password:(NSString *)password
confirmPassword:(NSString *)confirmPassword
completionBlock:(void (^)(NSMutableArray *resultsArray))completion{

NSLog(@"REGISTER ACCOUNT CALLED!");

NSString *appendUrl = [NSString stringWithFormat:@"Account/Register"];

NSURL *aUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@""%@", @"xxx", appendUrl]];
NSLog(@"URL: %@",aUrl);

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];

[request setHTTPMethod:@"POST"];

[request addValue:@"application/json, text/plain, */*" forHTTPHeaderField:@"Accept"];
[request addValue:@"application/json;charset=UTF-8" forHTTPHeaderField:@"Content-Type"];

//build an info object and convert to json
NSDictionary* info = [NSDictionary dictionaryWithObjectsAndKeys:
email,
@"Email",
password,
@"Password",
confirmPassword,
@"ConfirmPassword",
nil];

//convert object to data
NSError *error;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:info
options:NSJSONWritingPrettyPrinted error:&error];

NSString *strData = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"%@",strData);

[request setHTTPBody:[strData dataUsingEncoding:NSUTF8StringEncoding]];

[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

// NSLog(@"REGISTER PUSH NOTIFICATIONS RESPONSE: %@", response);
// NSLog(@"REGISTER PUSH NOTIFICATIONS ERROR: %@", error);
// NSLog(@"REGISTER PUSH NOTIFICATIONS DATA: %@", data);

NSData *_data = data;
NSMutableString *_string = [NSMutableString stringWithString:@""];
for (int i = 0; i < _data.length; i++) {
unsigned char _byte;
[_data getBytes:&_byte range:NSMakeRange(i, 1)];
if (_byte >= 32 && _byte < 127) {
[_string appendFormat:@"%c", _byte];
} else {
[_string appendFormat:@"[%d]", _byte];
}
}

NSLog(@"REGISTER ACCOUNT RESPONSE: %@", _string);

if(_string) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
completion((NSMutableArray*)_string);
}
}];
}


Response object:
enter image description here

Answer

This line is all wrong:

completion((NSMutableArray*)_string);

_string is an instance of NSMutableString, and here you're telling the compiler to trust you that it's actually an instance of NSMutableArray. This is obviously a lie and when you try to use it as an array you get an exception.

Note that the JSON could be an array or a dictionary, and in your example it is actually a dictionary, so you need to check this and work out how to return an array - or change the completion block. You need to explicitly deal with this container type variation somewhere...

You don't need to do the funky data to string processing you have, you can just use NSJSONSerialization to go straight from data to JSON object (dictionary or array), and it'll return an error if there is some issue with the JSON.

Hmmm, looking at that data processing again indicates some reformatting of the data, which is a bit weird but ok. After you've done that and got your string you should turn it back into data and then use NSJSONSerialization.