NSMutabel 2 dimensional array not working - objective-c

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?

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:
The user was using the SBJson library to parse the return value from his php web service.
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!

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.

Related

FatSecret API "invalid signature"

Using this repository I was not able to make the queries work when oauth_token must be provided. I always get invalid signature. Tried a lot of solutions and tweaks in the code, nothing worked. Please help.
This is the code from the git mentioned:
NSString *OAuthorizationHeader(NSURL *url, NSString *method, NSData *body, NSString *_oAuthConsumerKey, NSString *_oAuthConsumerSecret, NSString *_oAuthToken, NSString *_oAuthTokenSecret)
{
NSString *_oAuthNonce = [NSString ab_GUID];
NSString *_oAuthTimestamp = [NSString stringWithFormat:#"%d", (int)[[NSDate date] timeIntervalSince1970]];
NSString *_oAuthSignatureMethod = #"HMAC-SHA1";
NSString *_oAuthVersion = #"1.0";
NSMutableDictionary *oAuthAuthorizationParameters = [NSMutableDictionary dictionary];
[oAuthAuthorizationParameters setObject:_oAuthNonce forKey:#"oauth_nonce"];
[oAuthAuthorizationParameters setObject:_oAuthTimestamp forKey:#"oauth_timestamp"];
[oAuthAuthorizationParameters setObject:_oAuthSignatureMethod forKey:#"oauth_signature_method"];
[oAuthAuthorizationParameters setObject:_oAuthVersion forKey:#"oauth_version"];
[oAuthAuthorizationParameters setObject:_oAuthConsumerKey forKey:#"oauth_consumer_key"];
if(_oAuthToken)
[oAuthAuthorizationParameters setObject:_oAuthToken forKey:#"oauth_token"];
// get query and body parameters
NSDictionary *additionalQueryParameters = [NSURL ab_parseURLQueryString:[url query]];
NSDictionary *additionalBodyParameters = nil;
if(body) {
NSString *string = [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding];
if(string) {
additionalBodyParameters = [NSURL ab_parseURLQueryString:string];
}
}
// combine all parameters
NSMutableDictionary *parameters = [oAuthAuthorizationParameters mutableCopy];
if(additionalQueryParameters) [parameters addEntriesFromDictionary:additionalQueryParameters];
if(additionalBodyParameters) [parameters addEntriesFromDictionary:additionalBodyParameters];
// -> UTF-8 -> RFC3986
NSMutableDictionary *encodedParameters = [NSMutableDictionary dictionary];
for(NSString *key in parameters) {
NSString *value = [parameters objectForKey:key];
[encodedParameters setObject:[value ab_RFC3986EncodedString] forKey:[key ab_RFC3986EncodedString]];
}
NSArray *sortedKeys = [[encodedParameters allKeys] sortedArrayUsingFunction:SortParameter context:(__bridge void *)(encodedParameters)];
NSMutableArray *parameterArray = [NSMutableArray array];
for(NSString *key in sortedKeys) {
[parameterArray addObject:[NSString stringWithFormat:#"%#=%#", key, [encodedParameters objectForKey:key]]];
}
NSString *normalizedParameterString = [parameterArray componentsJoinedByString:#"&"];
NSLog(#"normalizedParameters: %#", normalizedParameterString);
NSString *normalizedURLString;
if ([url port] == nil) {
normalizedURLString = [NSString stringWithFormat:#"%#://%#%#", [url scheme], [url host], [url path]];
} else {
normalizedURLString = [NSString stringWithFormat:#"%#://%#:%#%#", [url scheme], [url host], [url port], [url path]];
}
NSString *signatureBaseString = [NSString stringWithFormat:#"%#&%#&%#",
[method ab_RFC3986EncodedString],
[normalizedURLString ab_RFC3986EncodedString],
[normalizedParameterString ab_RFC3986EncodedString]];
NSLog(#"signature base: %#", signatureBaseString);
NSString *key = [NSString stringWithFormat:#"%#&%#&",
[_oAuthConsumerSecret ab_RFC3986EncodedString],
[_oAuthTokenSecret ab_RFC3986EncodedString]];
NSLog(#"key codes: %#", key);
NSData *signature = HMAC_SHA1(signatureBaseString, key);
NSString *base64Signature = [signature base64EncodedString];
// PARKER CHANGE: changed oAuthAuthorizationParameters to parameters
NSMutableDictionary *authorizationHeaderDictionary = [parameters mutableCopy];
[authorizationHeaderDictionary setObject:base64Signature forKey:#"oauth_signature"];
NSMutableArray *authorizationHeaderItems = [NSMutableArray array];
for(NSString *key in authorizationHeaderDictionary) {
NSString *value = [authorizationHeaderDictionary objectForKey:key];
NSLog(#"KEY: %#", key);
NSLog(#"VALUE: %#", value);
// PARKER CHANGE: removed quotes that surrounded each value
[authorizationHeaderItems addObject:[NSString stringWithFormat:#"%#=%#",
[key ab_RFC3986EncodedString],
[value ab_RFC3986EncodedString]]];
}
// PARKER CHANGE: changed concatentation string from ", " to "&"
NSString *authorizationHeaderString = [authorizationHeaderItems componentsJoinedByString:#"&"];
// authorizationHeaderString = [NSString stringWithFormat:#"OAuth %#", authorizationHeaderString];
NSLog(#"final: %#", authorizationHeaderString);
return authorizationHeaderString;
}
And this is how I'm calling it:
- (void) makeUserRequestWithMethod:(NSString *)method
parameters:(NSDictionary *)params
completion:(void (^)(NSDictionary *data))completionBlock {
NSLog(#"%s", __func__);
NSMutableDictionary *parameters = [params mutableCopy];
[parameters addEntriesFromDictionary:[self defaultParameters]];
[parameters addEntriesFromDictionary:#{ #"method" : method }];
NSString *queryString = [self queryStringFromDictionary:parameters];
NSData *data = [NSData dataWithBytes:[queryString UTF8String] length:queryString.length];
NSString *authHeader = OAuthorizationHeader([NSURL URLWithString:FAT_SECRET_API_ENDPOINT],
#"POST",
data,
_oauthConsumerKey,
_oauthConsumerSecret,
_oAuthToken,
_oAuthTokenSecret
);
NSLog(#"header: %#", authHeader);
NSURL *url = [NSURL URLWithString:[FAT_SECRET_API_ENDPOINT stringByAppendingFormat:#"?%#", authHeader]];
[[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (data) {
id JSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
completionBlock(JSON);
} else {
completionBlock(nil);
}
}] resume];
}
I'm going to go out on a limb here and say that the code that others have proven to work is probably not at fault here, but rather first look at your own code. You say the error messages is "Invalid Signature" which sounds like it's a warning from the server you're calling, not from the code you're using.
[parameters addEntriesFromDictionary:[self defaultParameters]];
[parameters addEntriesFromDictionary:#{ #"method" : method }];
NSString *queryString = [self queryStringFromDictionary:parameters];
What happens inside [self defaultParameters] and are you 100% certain the parameters are appropriate (including spelling) for the API you're calling?
Have you verified that [self queryStringFromDictionary:parameters] prepares a properly formatting query string, and isn't introducing some error (non-escaped special characters, or percent encoding, for example)?

reading plist file crashes

read in did load:
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) //4
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"]; //5
[fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
}
//load in text fields.
NSMutableDictionary *savedData = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
nameField.text = [[savedData objectForKey:#"name"] stringValue];
locationTextField.text = [[savedData objectForKey:#"location"] stringValue];
sectorTextField.text = [[savedData objectForKey:#"sector"] stringValue];
Write on button click:
- (IBAction)writingButton:(id)sender
{
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//[data setObject:[NSNumber numberWithInt:value] forKey:#"value"];
[data setObject:[NSString stringWithString:nameField.text] forKey:#"name"];
[data setObject:[NSString stringWithString:locationTextField.text] forKey:#"location"];
[data setObject:[NSString stringWithString:sectorTextField.text] forKey:#"sector"];
}
the plist file:
The error:
2012-09-04 17:03:40.360 app[4849:c07] -[__NSCFString stringValue]:
unrecognized selector sent to instance 0x6aa38f0 2012-09-04
17:03:40.362 app[4849:c07] *** Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[__NSCFString
stringValue]: unrecognized selector sent to instance 0x6aa38f0'
Any ideas? cheers.
The dictionary stores NSString objects directly - there's no need to call a (nonexistent) method called - stringValue. Simply write
nameField.text = [savedData objectForKey:#"name"];
and so on.
(Why do you think this method call would have been necessary?)

Searching a custom tableviewCell

I want to do a search in a tableview. But in this table view I work with a custom tableview Cell. So for the data part. I select in a view a categorie. Then in the next view I get all the products within this categorie.
I followed a tutorial and implemented all the methods.
This is my function for getting the products.
-(void) fillArrayProducts:(NSString *)cat{
NSMutableString *postString = [NSMutableString stringWithString:kGETProducts];
[postString appendString:[NSString stringWithFormat:#"?%#=%#",#"Pro_cat",cat]];
[postString setString:[postString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *request= [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:postString]];
[request setHTTPMethod:#"POST"];
postConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:postString]];
NSError *error;
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
arrayProducts = [[NSMutableArray alloc] init];
copyArrayProducts = [[NSMutableArray alloc] init];
arrayProductNaam = [[NSMutableArray alloc] init];
for (int i=0; i<[json count]; i++) {
arrayProduct = [[NSMutableArray alloc] init];
[arrayProduct addObject:[json objectAtIndex:i]];
[arrayProducts addObject:arrayProduct];
[arrayProductNaam addObject:[[[arrayProducts valueForKey:#"Pro_naam"] objectAtIndex:i]objectAtIndex:0]];
[copyArrayProducts addObject:arrayProduct];
}
NSDictionary *productsDict = [NSDictionary dictionaryWithObject:arrayProductNaam forKey:#"Products"];
NSLog(#"%#",arrayProductNaam);
}
No what I'm doing. I have an array 'arrayProducts' in this array I put arrays from 'arrayProduct'. In arrayProduct you can find Pro_id,Pro_naam,Pro_prijs. But I only want to search on Pro_naam. So I fill also an array (arrayProductNaam) with only the products names.
So here is the part were I do my search.
- (void) searchTableView {
NSString *searchText = searchbar.text;
NSMutableArray *searchArray = [[NSMutableArray alloc] init];
for (NSDictionary *dictionary in arrayProductNaam)
{
NSArray *array = [dictionary objectForKey:#"Pro_naam"];
[searchArray addObjectsFromArray:array];
}
for (NSString *sTemp in searchArray)
{
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
[copyArrayProducts addObject:sTemp];
}
}
I think that it's here were I getting this error.
2012-02-02 13:22:40.958 MamzelBestelling2[23727:f803] -[__NSCFString
objectForKey:]: unrecognized selector sent to instance 0x6c34780
2012-02-02 13:22:40.959 MamzelBestelling2[23727:f803] *** Terminating
app due to uncaught exception 'NSInvalidArgumentException', reason:
'-[__NSCFString objectForKey:]: unrecognized selector sent to instance
0x6c34780'
You are not filling arrayProductNaam with Dictionary. Its filled by NSString. Now, in the searchTableView function you are handling these string members as Dictionaries and hence the problem.
try to NSLog your String Array. so you can get the idea it exist or not
you are trying to get a keyValue from a string not from a dictionary.

Want to split the JSON from the URL not the response

I want to split the json part from this URL in my iPhone application.
http://vkontakte.ru/login_success.html#session={"expire":"1272008089","mid":"100172","secret":"9c8d8f0305","sid":"1131703552161ae352a1256402e3140d7cbde41b1602a93d15472c82"}
I tried and and saved the JSON into a NSString but what i am getting is
http://vkontakte.ru/api/login_success.html?session=%7B%22mid%22:113158415,%22secret%22:%227ce58bfcd3%22,%22sid%22:%2203831b43c1bb992f9477efbfe96e83f6ecff1c1b661315ac0a20719cf57a44%22,%22expire%22:0%7D
This is not coming in JSOn Format. Below is my code
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSError* error;
NSLog (#"json path %#",url);
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSURLRequest *request1 = [NSURLRequest requestWithURL:url];
NSString *json_string = [url absoluteString];
NSArray *arr = [json_string componentsSeparatedByString:#"="];
json_string = [arr objectAtIndex:1];
// parse the JSON response into an object
// Here we're using NSArray since we're parsing an array of JSON status objects
NSArray *statuses = [json_string JSONValue];
NSLog(#"%#",error);
// Each element in statuses is a single status
// represented as a NSDictionary
for (NSDictionary *status in statuses)
{
// You can retrieve individual values using objectForKey on the status NSDictionary
// This will print the tweet and username to the console
NSLog(#"%# - %#", [status objectForKey:#"secret "], [[status objectForKey:#"mid"] objectForKey:#"sid"]);
}
return YES;
}
How can move further?
Try replacing:
NSString *json_string = [url absoluteString];
with
NSString *json_string = [[url absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];.
That's a really strange thing you're doing, though. Why does the URL have JSON in it?

Objective-C file i/o error

- (IBAction)sendMessage:(id)sender
{
NSString* conversationFile = [#"~/" stringByAppendingPathComponent:#"conversation.txt"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:conversationFile];
if (fileExists == FALSE)
{
[self doShellScript:#"do shell script \"cd ~/; touch conversation.txt\""];
}
NSString *conversationContent = [[NSString alloc] stringWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];
NSString *myMessage = [[messageBox stringValue]copy];
NSString *combinedContent = [NSString stringWithFormat:#"%# \r\n %#", conversationContent, myMessage];
[[[myConversationBox textStorage] mutableString] setString: combinedContent];
[combinedContent writeToFile:#"~/conversation.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}
The above code presents the following error
2011-07-07 21:38:08.703
iMessages[86493:903]
-[NSPlaceholderString stringWithContentsOfFile:encoding:error:]:
unrecognized selector sent to instance
0x100111690
2011-07-07 21:38:08.704
iMessages[86493:903]
-[NSPlaceholderString stringWithContentsOfFile:encoding:error:]:
unrecognized selector sent to instance
0x100111690
stringWithContentsOfFile:encoding:error: is a class method of NSString, not an instance method, so you don't need to (shouldn't) alloc it first.
NSString *conversationContent = [NSString stringWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];
Use initWithContentsOfFile in place of stringWithContentsOfFile or remove the alloc call. So have:
NSString *conversationContent = [[NSString alloc] initWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];
or
NSString *conversationContent = [NSString stringWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];