I want to ask about the iPhone application objective C problem.
I wrote a program to store the cookies and pass to another URL to retrieve the cookies.
However, I found that one of the return status code is 0. The content of the html is empty.
Can any one help me?
The following is my code.
// create a new mutable url
NSMutableURLRequest *request_get2 = [[[NSMutableURLRequest alloc] init] autorelease];
[request_get2 setURL:[NSURL URLWithString:#"http://www.example.com"]];
[request_get2 setHTTPMethod:#"GET"];
[request_get2 setValue:#"text/html; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[request_get2 setValue:#"http://www.example.com" forHTTPHeaderField:#"Referer"];
[request_get2 setHTTPShouldHandleCookies:YES];
// cookiesString is a string, the format is "cookieName=cookieValue;"
[request_get2 setValue: (NSString *) cookiesString forHTTPHeaderField:#"Cookie"];
// doGet - response
NSHTTPURLResponse *response_get2 = nil;
NSError *error_get2 = nil;
NSData *responseData_get2 = [NSURLConnection sendSynchronousRequest:request_get2 returningResponse:&response_get2 error:&error_get2];
NSString *data_get2 = [[NSString alloc]initWithData:responseData_get2 encoding:NSUTF8StringEncoding];
NSString *responseURL_get2 = [[response_get2 URL] absoluteString]; // null value
NSString *responseTextEncodingName_get2 = [response_get2 textEncodingName]; // null value
NSString *responseMIMEType_get2 = [response_get2 MIMEType]; // null value
NSUInteger *responseStatusCode_get2 = [response_get2 statusCode]; //[responseStatusCode intValue]; // the status code is 0
Thank you very much
If you get a 0 for a response code, the response response_get2 probably was never initialized, which might point to a problem with the request unrelated to your web server.
You set error_get2, so check its value after the request is placed:
if (!error_get2) {
NSString *responseURL_get2 = [[response_get2 URL] absoluteString]; // null value
NSString *responseTextEncodingName_get2 = [response_get2 textEncodingName]; // null value
NSString *responseMIMEType_get2 = [response_get2 MIMEType]; // null value
NSUInteger *responseStatusCode_get2 = [response_get2 statusCode]; //[responseStatusCode intValue]; // the status code is 0
}
else {
NSLog(#"something went wrong: %#", [error_get2 userInfo]);
}
Related
Here is the authorization header I use:
Authorization = "OAuth oauth_consumer_key=\"2D9rLD8Lu23hrchrh4VMBkQ6AZKHYi2yY2oeuoeutcFMdAs\", oauth_nonce=\"-486353546\", oauth_signature="x3NdGnJmBTUAICBRE9C44N8mFd4%3D", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"137663828056\", oauth_version=\"1.0\", x_auth_mode=\"reverse_auth\"";
Here's the base string I use:
https://api.twitter.com/oauth/access_token
Here's the twitter documentation I'm working from:
Step 1: Obtain a Special Request Token
First, you make an HTTPS request to the Twitter Request Token URL
https://api.twitter.com/oauth/request_token with your application's
consumer key. In addition to the conventional oauth_* signing
parameters, you must also include x_auth_mode set to the value
reverse_auth.
As an example, consider a request with the following values signed
with the token secret ydC2yUbFaScbSlykO0PmrMjXFeLraSi3Q2HfTOlGxQM:
The tokens used here are for demonstration purposes only, and will not
work for you.
oauth_consumer_key JP3PyvG67rXRsnayOJOcQ oauth_nonce
1B7D865D-9E15-4ADD-8165-EF90D7A7D3D2 oauth_signature_method HMAC-SHA1
oauth_timestamp 1322697052 oauth_version 1.0 x_auth_mode reverse_auth
These parameters should result in a signature base string that looks
like this:
POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_consumer_key%3DJP3PyvG67rXRsnayOJOcQ%26oauth_nonce%3D1B7D865D-9E15-4ADD-8165-EF90D7A7D3D2%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1322697052%26oauth_version%3D1.0%26x_auth_mode%3Dreverse_auth
This call should result in a response that looks like this. Notice
that this response actually looks like an OAuth header.
(line wrapping added for clarity):
OAuth oauth_nonce="xq2maKtilFhVTC1MSxVC4cQIJLd53O6w97YmrdOGSk8",
oauth_signature_method="HMAC-SHA1", oauth_timestamp="1322697052",
oauth_consumer_key="JP3PyvG67rXRsnayOJOcQ",
oauth_token="5mgkU82W0PTA0DLgSIA5vFK6c08i8dXzrbLnX06vl38",
oauth_signature="aOM%2FwW2kAowAeHBRvw7faH245p0%3D",
oauth_version="1.0"
Edit: I still get a 401. I used the following code to generate the oauth_signature, so now my Authorization header looks like this: OAuth oauth_timestamp="1376639141", oauth_nonce="BB2D2634F3-99A5-4B64-8CB34E-2314CE9E4FD7", oauth_version="1.0", oauth_consumer_key="mrcD8LuSNKJKFAchKHYi2yY2qwh5tcFMdAs", oauth_signature_method="HMAC-SHA1", oauth_signature="moer8H7xzluAdoAAAFZpv6n4noeu%3D"
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[#"oauth_nonce"] = _oAuthNonce;
oAuthAuthorizationParameters[#"oauth_timestamp"] = _oAuthTimestamp;
oAuthAuthorizationParameters[#"oauth_signature_method"] = _oAuthSignatureMethod;
oAuthAuthorizationParameters[#"oauth_version"] = _oAuthVersion;
oAuthAuthorizationParameters[#"oauth_consumer_key"] = _oAuthConsumerKey;
if(_oAuthToken)
oAuthAuthorizationParameters[#"oauth_token"] = _oAuthToken;
// 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] autorelease];
if(string) {
additionalBodyParameters = [NSURL ab_parseURLQueryString:string];
}
}
// combine all parameters
NSMutableDictionary *parameters = [[oAuthAuthorizationParameters mutableCopy] autorelease];
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[key];
encodedParameters[[key ab_RFC3986EncodedString]] = [value ab_RFC3986EncodedString];
}
NSArray *sortedKeys = [[encodedParameters allKeys] sortedArrayUsingFunction:SortParameter context:encodedParameters];
NSMutableArray *parameterArray = [NSMutableArray array];
for(NSString *key in sortedKeys) {
[parameterArray addObject:[NSString stringWithFormat:#"%#=%#", key, encodedParameters[key]]];
}
NSString *normalizedParameterString = [parameterArray componentsJoinedByString:#"&"];
NSString *normalizedURLString = [NSString stringWithFormat:#"%#://%#%#", [url scheme], [url host], [url path]];
NSString *signatureBaseString = [NSString stringWithFormat:#"%#&%#&%#",
[method ab_RFC3986EncodedString],
[normalizedURLString ab_RFC3986EncodedString],
[normalizedParameterString ab_RFC3986EncodedString]];
NSString *key = [NSString stringWithFormat:#"%#&%#",
[_oAuthConsumerSecret ab_RFC3986EncodedString],
(_oAuthTokenSecret) ? [_oAuthTokenSecret ab_RFC3986EncodedString] : #""];
NSData *signature = HMAC_SHA1(signatureBaseString, key);
NSString *base64Signature = [signature base64EncodedString];
NSMutableDictionary *authorizationHeaderDictionary = [[oAuthAuthorizationParameters mutableCopy] autorelease];
authorizationHeaderDictionary[#"oauth_signature"] = base64Signature;
NSMutableArray *authorizationHeaderItems = [NSMutableArray array];
for(NSString *key in authorizationHeaderDictionary) {
NSString *value = authorizationHeaderDictionary[key];
[authorizationHeaderItems addObject:[NSString stringWithFormat:#"%#=\"%#\"",
[key ab_RFC3986EncodedString],
[value ab_RFC3986EncodedString]]];
}
NSString *authorizationHeaderString = [authorizationHeaderItems componentsJoinedByString:#", "];
authorizationHeaderString = [NSString stringWithFormat:#"OAuth %#", authorizationHeaderString];
return authorizationHeaderString;
}
The parameters I pass in to this method are
url: https://api.twitter.com/oauth/request_token, method: POST, body: nil, oAuthConsumerToken: my key, oAuthConsumerSecret: my secret, oAuthToken:nil,oAuthTokenSecret:nil.
EDIT I tried this oauth test console to verify that I'm properly generating the oauth signature, but it appears I need the Member's token and secret:
You haven't included the oauth_signature in the Authorization header.
I'm diving into iOS development and I have a custom URL scheme for my iPhone app that looks like myApp://?q=200. I have the following code to get the query parameter...
NSString *urlString = [url absoluteString];
NSString *query = [urlString stringByReplacingOccurrencesOfString:#"myApp://?q=" withString:#""];
...but I'd like to make it a bit more future-proof in the event that I add more parameters. How can I extract the "q" parameter in a safer way?
Thanks in advance for your wisdom!
You can split the query returned from the URL by & and = and put them in a dictionary.
NSURL *url = [NSURL URLWithString:#"myApp://?q=200"];
NSArray *query = [[url query] componentsSeparatedByString:#"&"];
NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithCapacity:[query count]];
for(NSString *parameter in query)
{
NSArray *kv = [parameter componentsSeparatedByString:#"="];
[parameters setObject:[kv count] > 1 ? [[kv objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding] : [NSNull null]
forKey:[[kv objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding]];
}
NSLog(#"Parameters: %#", parameters);
NSLog(#"q = %#", [parameters objectForKey:#"q"]);
In this example if there is no value for the parameter I just set it to NSNull. This means you would either need to check for NSNull or change the logic to skip keys with values or set them to an empty string.
This from the top of my head could work but doesnt yet include error checking the input
-(NSDictionary*) parameterDictionaryFromString: (NSURL*) url {
//input can be something like: "myApp://?q=one&q2=two&q3=three"
NSString *requestString = [url query];
//now we have q=one&q2=two&q3=three
NSArray *requests = [requestString componentsSeparatedByString: #"&"];
NSMutableDictionary *resultDictionary = [NSMutableDictionary dictionary];
for (NSString *singleParameter in requests) {
NSArray *keyValuePair = [singleParameter componentsSeparatedByString: #"="];
[resultDictionary setObject: [keyValuePair objectAtIndex: 1] forKey: [keyValuePair objectAtIndex: 0]];
}
NSURL *u = [NSURL URLWithString: #"myApp://something?q=1&check=yes"];
NSLog(#"paramStr = %#", [u parameterString]);
return [resultDictionary copy];
}
Break the Query String by Distinct Separator,
Assure Valued Content provided at index:1 (The right-hand side of the query string break)
In valued content then use downstream, or set to upstream variable.
//Your Example:
//#"myApp://?q=200"
//Break:
NSArray *queryParts = [urlString componentsSeparatedByString:#"?q="];
//Assure Content:
if ([[array objectAtIndex:1] length]>0) {
//Setter:
NSString *queryString = [array objectAtIndex:1];
//... Use away...
}
The key is to leverage the NSArray class over StringReplace.
Hi I have this code.
NSString *infoString = [NSString stringWithFormat:#"http://link.com/post.php?name=%#&street=%#&city=%#&state=%#&zip=%#&lat=%#&lon=%#", name, street, city, state, zip, str1, str2];
NSURL *infoUrl = [NSURL URLWithString:infoString];
NSData *infoData = [NSData dataWithContentsOfURL:infoUrl];
NSError *error;
responseDict = [NSJSONSerialization JSONObjectWithData:infoData options:0 error:&error];
NSString *responseString = [responseDict copy];
NSLog(#"responseDict: %#", responseString);
In the console this shows up.
2012-06-14 22:37:04.022 PartyApp[20221:fb03] responseDict: {
status = 1;
}
Is there anyway I can make an if statement to show that if the value is 1 then do this and if it's not then do this. I have tried below.
if ([responseDict objectForKey:#"status = 1"]) {
Then do this
}
But it didn't work, what am I doing wrong or what could I do?
if ([responseDict objectForKey:#"status = 1"]) {
Then do this
}
should be..
if ([responseDict objectForKey:#"status"]) {
//this will be done in case of 1
}else{
//this will be done in case of 0
}
only status is the key not your entire thing.. hoping this helps..
update: The above lines are enough because of it reeturns 1 it will proceed else in case of 0 the condition is false and will go to the else clause
Is it possible to deserialize an NSString of JSON into objects via RestKit? I checked the API list here and could not find something that would serve for this purpose. The closest I could find are the various parser classes that return NSDictionary after parsing the input. I assume RestKit uses these parsers after downloading the response so my thinking is that the functionality is available somewhere in RestKit but not exposed publicly.
If I am not missing anything and this functionality is not exposed, what would be the alternatives? Two obvious ones do not look very promising: Get the resulting NSDictionary and try to deserialize myself (effectively reimplementing RestKit) or try to dive into RestKit source and see if this can be somehow exposed (looks tedious and error prone).
Thanks in advance for any help.
PS: The idea is that a string property on a deserialized object is actually the JSON representation of another set of objects (embedded JSON in a sense) and it is deserialized on demand during runtime.
Pretty "simple":
NSString *stringJSON;
...
RKJSONParserJSONKit *parser;
NSError *error= nil;
parser= [[[RKJSONParserJSONKit alloc] init] autorelease];
MyManagedObject *target;
target= [MyManagedObject object];
NSDictionary *objectAsDictionary;
RKObjectMapper* mapper;
objectAsDictionary= [parser objectFromString:stringJSON error:&error];
mapper = [RKObjectMapper mapperWithObject:objectAsDictionary
mappingProvider:[RKObjectManager sharedManager].mappingProvider];
mapper.targetObject = target;
RKObjectMappingResult* result = [mapper performMapping];
NSLog(#"%#", [result asObject]);
As of RestKit 0.20.0-pre2
NSString* JSONString = #"{ \"name\": \"The name\", \"number\": 12345}";
NSString* MIMEType = #"application/json";
NSError* error;
NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:MIMEType error:&error];
if (parsedData == nil && error) {
// Parser error...
}
AppUser *appUser = [[AppUser alloc] init];
NSDictionary *mappingsDictionary = #{ #"someKeyPath": someMapping };
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary];
mapper.targetObject = appUser;
NSError *mappingError = nil;
BOOL isMapped = [mapper execute:&mappingError];
if (isMapped && !mappingError) {
// Yay! Mapping finished successfully
NSLog(#"mapper: %#", [mapper representation]);
NSLog(#"firstname is %#", appUser.firstName);
}
This works for Restkit 0.21.0:
NSString* jsonFilePath = [[NSBundle mainBundle] pathForResource:#"fileName"
ofType:#"json"];
NSString* JSONString = [NSString stringWithContentsOfFile:jsonFilePath
encoding:NSUTF8StringEncoding
error:NULL];
NSError* error;
NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:&error];
if (parsedData == nil && error) {
// Parser error...
}
//_objectManager is RKObjectManager instance
NSMutableDictionary *mappingsDictionary = [[NSMutableDictionary alloc] init];
for (RKResponseDescriptor *descriptor in _objectManager.responseDescriptors) {
[mappingsDictionary setObject:descriptor.mapping forKey:descriptor.keyPath];
}
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary];
NSError *mappingError = nil;
BOOL isMapped = [mapper execute:&mappingError];
if (isMapped && !mappingError) {
NSLog(#"result %#",[mapper mappingResult]);
}
This works for Restkit 0.20, using Core Data Entities. It is based in the solution given by #innerself
NSString* jsonFilePath = [[NSBundle mainBundle] pathForResource:#"info-base"
ofType:#"json"];
NSString* JSONString = [NSString stringWithContentsOfFile:jsonFilePath
encoding:NSUTF8StringEncoding
error:NULL];
NSError *error = nil;
NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:&error];
if (parsedData == nil && error) {
// Parser error...
NSLog(#"parse error");
}
//_objectManager is RKObjectManager instance
NSMutableDictionary *mappingsDictionary = [[NSMutableDictionary alloc] init];
for (RKResponseDescriptor *descriptor in [RKObjectManager sharedManager].responseDescriptors) {
[mappingsDictionary setObject:descriptor.mapping forKey:descriptor.keyPath];
}
RKManagedObjectMappingOperationDataSource *datasource = [[RKManagedObjectMappingOperationDataSource alloc]
initWithManagedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext
cache:[RKManagedObjectStore defaultStore].managedObjectCache];
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData
mappingsDictionary:mappingsDictionary];
[mapper setMappingOperationDataSource:datasource];
NSError *mappingError = nil;
BOOL isMapped = [mapper execute:&mappingError];
if (isMapped && !mappingError) {
// data is in [mapper mappingResult]
}
You can see how RestKit does this internally in the RKManagedObjectResponseMapperOperation class.
There are three stages of this operation.
The first is to parse the JSON string into NSDictionarys, NSArrays, etc. This is the easiest part.
id parsedData = [RKMIMETypeSerialization objectFromData:data
MIMEType:RKMIMETypeJSON
error:error];
Next you need to run a mapping operation to convert this data into your NSManagedObjects. This is a bit more involved.
__block NSError *blockError = nil;
__block RKMappingResult *mappingResult = nil;
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 1;
[[RKObjectManager sharedManager].managedObjectStore.persistentStoreManagedObjectContext performBlockAndWait:^{
Remember to replace this dictionary with your own mappings. The key [NSNull null] maps this object from the root.
NSDictionary *mappings = #{[NSNull null]: [jotOfflineRequestStatus mapping]};
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData
mappingsDictionary:mappings];
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc]
initWithManagedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext
cache:[RKManagedObjectStore defaultStore].managedObjectCache];
dataSource.operationQueue = operationQueue;
dataSource.parentOperation = mapper;
mapper.mappingOperationDataSource = dataSource;
[mapper start];
blockError = mapper.error;
mappingResult = mapper.mappingResult;
}];
You now need to run the tasks that have been put into the operationQueue we created. It is at this stage that connections to existing NSManagedObjects are made.
if ([operationQueue operationCount]) {
[operationQueue waitUntilAllOperationsAreFinished];
}
A more iOS 5+ oriented answer:
NSString* JSONString = jsonString;
NSString* MIMEType = #"application/json";
NSError* error = nil;
id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:MIMEType];
id parsedData = [parser objectFromString:JSONString error:&error];
if (parsedData == nil && error) {
NSLog(#"ERROR: JSON parsing error");
}
RKObjectMappingProvider* mappingProvider = [RKObjectManager sharedManager].mappingProvider;
RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider];
RKObjectMappingResult* result = [mapper performMapping];
if (result) {
NSArray *resultArray = result.asCollection;
MyObject *object = [resultArray lastObject];
NSLog(#"My Object: %#", object);
}
For Restkit 0.22, You can use this code. This returns an RKMappingResult wherein you can enumerate the objects after mapping using the property .array.
- (RKMappingResult *)mapJSONStringWithString:(NSString *)jsonString
{
RKMappingResult *result = nil;
NSError* error;
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:&error];
if (parsedData == nil && error) {
NSLog(#"json mapping error");
}
NSDictionary *mappingsDictionary = #{#"":[CustomMappingClass getMappingForUsers]};
ObjectClass *obj = [ObjectClass new];
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary];
NSError *mappingError = nil;
mapper.targetObject = obj;
BOOL isMapped = [mapper execute:&mappingError];
if (isMapped && !mappingError) {
result = [mapper mappingResult];
}
return result;
}
Is this not what you're looking for? http://restkit.org/api/0.10.0/Classes/RKJSONParserJSONKit.html
Judging by the views without any answers, it seems this facility does not exist in RestKit yet. Instead of spending more time trying to figure out how to do the mapping, I wrote my own mapper using the output of JsonKit parser and removed the dependency on RestKit (used the builtin classes for network activity). Right now my mapper is not generic (it has a few dependencies on how the objects are laid out and their names in json) but it works for the purposes of the project. I might come back later and turn it into a more generic object mapping library later on.
EDIT: This was selected answer because there was no other answer as of this answer's date (Jan 21, 2012). Since then, I stopped working on iOS and never visited this question again. Now I am selecting Ludovic's answer because of another user's comment and the upvotes for that answer.
Currently I am using the following code to parse the JSON link sent. This is how I also send a GET call to the Google Reader API for an upcoming iPhone application of mine.
- (NSArray *)subscriptionList
{
if(!cookies && [cookies count] == 0) {
[self requestSession];
}
NSString * url = #"http://www.google.com/reader/api/0/subscription/list?output=json&client=scroll";
ASIHTTPRequest * request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
[request setRequestMethod:#"GET"];
[request setRequestCookies:cookies];
[request addRequestHeader:#"Authorization" value:[NSString stringWithFormat:#"GoogleLogin auth=%#", [self auth]]];
[request startSynchronous];
subfeeds = [NSMutableArray array];
// Create new SBJSON parser object
SBJSON *parser = [[SBJSON alloc] init];
if ([request responseStatusCode] == 200) {
NSData * sixty = [request responseData];
NSString * body = [[NSString alloc] initWithData:sixty encoding:NSUTF8StringEncoding];
if (body) {
NSArray *feeds = [parser objectWithString:body error:nil];
NSLog(#"Array Contents: %#", [feeds valueForKey:#"subscriptions"]);
NSLog(#"Array Count: %d", [feeds count]);
NSDictionary *results = [body JSONValue];
NSArray *ohhai = [results valueForKey:#"subscriptions"];
for (NSDictionary *title in ohhai) {
subTitles = [title objectForKey:#"title"];
NSLog(#"title is: %#",subTitles);
}
}
}
return subfeeds;
[subTitles release];
[parser release];
}
I can successfully parse the JSON using the above code, and it successfully outputs the titles into NSLog. In my RootViewController.m, I call the following to grab this -(NSArray *)subscriptionList.
-(void)viewDidAppear:animated {
GoogleReader * reader = [[GoogleReader alloc] init];
[reader setEmail:gUserString];
[reader setPassword:gPassString];
//feedItems is a NSArray where we store the subscriptionList NSArray
feedItems = [reader subscriptionList];
//NSString *feedTitle = [];
NSLog(#"%#", feedItems);
[reader release];
// the rest of the function
}
The code above successfully works with the credentials entered. As you can see there is also a commented NSString called feedTitle. This is where I want to pull the #"title" from the parsed JSON but I do not know how to call it.
Any help would be greatly appreciated!
This is what the JSON source looks like:
{"subscriptions":
[
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""},
{"id":"","title":"","categories":[],"sortid":"","firstitemmsec":""}
]
}
I'm interested in only the "title" node.
Well, it would help if you added the source JSON but it's quite easy to grasp how SBJSON parses incoming JSON.
Just an example:
{ "myOutDict" : { "key1": "val1" , "key2" : "val2"} }
This JSON String would be parsed so you can access it by using this code
NSDictionary* myOuterdict = [feeds valueForKey:#"myOutDict"]);
NSString* val1 = [myOuterdict valueForKey:#"key1"]);
NSString* val2 = [myOuterdict valueForKey:#"key2"]);
Edit: Checked my personal Google Reader feed:
The JSON looks like this
{
"subscriptions": [{
"id": "feed/http://adambosworth.net/feed/",
"title": "Adam Bosworth's Weblog",
"categories": [],
"sortid": "0B5B845E",
"firstitemmsec": "1243627042599"
},
{
"id": "feed/http://feeds.feedburner.com/zukunftia2",
"title": "Zukunftia",
"categories": [],
"sortid": "FCABF5D4",
"firstitemmsec": "1266748722471"
}]
}
So the corresponding Objective C Code would be:
NSArray* subscriptions= [feeds valueForKey:#"subscriptions"]);
foreach(NSDictionary* item in subscriptions) {
// Do stuff
// NSString* title = [item valueForKey:#"title"]
// NSString* id = [item valueForKey:#"id"]
}
I'm not sure I understand the question. Are you trying to get a title for the feed as a whole, or per-item? Because I can't see a title property for the subscriptions array in the source JSON.