Parsing twitter-json in iPhone app - iphone

I used to have trouble parsing json, before I found a really good tutorial which I could follow. When I have been building my own webservices to parse json from I have followed the same steps, but now when I'm trying to parse twitters json-feed I'm drawing blanks. Here's my code.
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* itemNumber = [json objectForKey:#"posts"]; //2
NSUInteger numObjects = [itemNumber count];
arrayTweets = [[NSMutableArray alloc] init];
arrayTimes = [[NSMutableArray alloc] init];
if (numObjects != 0) {
int i = 0;
do
{
NSDictionary* loan = [itemNumber objectAtIndex:i];
NSString* text = [(NSDictionary*)loan objectForKey:#"text"];
[arrayTweets addObject:text];
NSString *time = [(NSDictionary*)loan objectForKey:#"created_at"];
[arrayTweets addObject:time];
i++;
} while (i < numObjects);
} else {
NSLog(#"Nej");
}
[tableTweet performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
Notice the "NSArray* itemNumber = [json objectForKey:#"posts"];". Since my old json-feed used to look something like this...
{"status":"ok","count":4,"count_total":4,"pages":1,"posts":[{"id":58,"type":
it was working since I had the "posts" before :[, but now with the twitter feed it just starts right into:
[{"created_at":"Mon Aug 06 19:16:42 +0000 2012","id":232555817835048961,"...
And I have no idea what to do. I realize this is stupid, but I don't think I'm going to learn unless someone explains it to me.
Any help appreciated!

Aah, there is a small problem with your code. The root object of your previous feed used to be a dictionary. You can see this by the { sign at the beginning. Your new feed instantly gives you an array back [. So you don't have to parse your data as a dictionary but as as NSArray. Without further ado, explanation here: https://stackoverflow.com/a/8356919/341358

Related

Pick out certain part of NSMutableAray

How would I pick out certain part of NSMutableArray?
One fielding array from server is 2012-09-01 09:00:00 America/Los_Angeles
I am trying to get just the time.
I was thinking turning it into a string and then getting it and then back into NSMutablearray to populate to tableview cells.
I am still looking at documentation
Options I am thinking of:
-subarrayWithRange:
componentsSeparatedByString:
UPDATE:
Here is what I am doing now to get the field of appointments
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error];
NSDictionary* myslots =[json objectForKey:#"slots"];
self.timesArray = [[NSMutableArray alloc] init];
NSLog(#"allslots: %#", myslots);
for (NSString *slotKey in myslots.allKeys) {
NSDictionary *slot = [myslots valueForKey:slotKey];
for (myDays in slot){
if ([[self.myDays objectForKey:#"isReservable"] isEqualToNumber:[NSNumber numberWithInt:1]])
[self.timesArray addObject:[self.myDays objectForKey:#"begin"]];
//NSLog(#"This is the times count: %#", timesArray.count);
}
}
NSLog(#"These are the times avail: %#", self.timesArray);
[self.tableView reloadData];
}
All I want eventually is an array of just the times. I am sorry if I am not being clear. I am trying to. Please let me know what information I can provide to paint a clearer picture
I'd save it as a string first
NSString *someString = [myArray objectAtIndex:index];
and then use something like NSMakeRange to get just that bit
[someString substringWithRange:NSMakeRange(11,18)];

how to get objects from a json array in iphone?

I am working on an iPhone app which involves using json-framework.I am getting array using NSURL
[{"firstName":"X","lastName":"Y","id":1},{"firstName":"A","lastName":"B","id":2}]
How can i get these 2 objects as like if i query for id=1, the O/P is
id=1
firstName:X
lastName:Y
and putting it in a table.
I am googling the stuff from many days but didn't get any solution.
Please help me out , explanation through code is appreciated.
Thank You.
If your target SDK is ios4 or higher, you can use this project
https://github.com/stig/json-framework/
Once you add the source to your project, just
#import "SBJson.h"
and convert your Json string as follows
jsonResponse = [string JSONValue];
The method will fail if you don't have the full Json array in your string, but you can keep appending strings until it doesn't fail
To follow up for codejunkie's request below
you can assume in your data structure that the jsonResponse is an NSArray
In other implementations take care to test the response for NSArray or NSDictionary
NSArray * myPeople = [string JSONValue];
NSMutableDictionary * organizedData = [[NSMutableDictionary alloc] init];
for (NSDictionary * p in myPeople) {
[organizedData setValue:p forKey:[p valueForKey:#"id"]];
}
// now you can query for an id like so
// [organizedData valueForKey:#"1"]; and your output will be what you wanted from the original question
// just don't forget to release organizedData when you are done with it
https://github.com/johnezang/JSONKit
I use this to get data from a webservice that spits out 50 records each having another 20 internal elements similar to the one you specify...
I use the JSONKit in the following manner..(Had a look at SBJson a lot of user but i got confused from the word go.)
JSONDecoder *jArray = [[JSONDecoder alloc]init];
NSMutableArray *theObject = [[NSMutableArray alloc] init];
theObject = [jArray objectWithData:theResponseData];//objectWithString:theResponseString
NSMutableArray *csArray = [[NSMutableArray array] retain] ;
for(id key in theObject)
{
if([key valueForKey:#"firstName"] != Nil)
{
........
}
if([key valueForKey:#"lastName"] != Nil)
{
........
}
}
check it out and let me know if it works or not.. By the way Great responses guys... Good

GData Objective C client memory leak

I have a method where I fetch GDataFeedBase entries and return these as an array to another function
NSMutableArray *tempFeedArray = [NSMutableArray array];
NSURL *feedURL = [[NSURL alloc] initWithString:escapedUrlString];
NSData *data = [NSData dataWithContentsOfURL:feedURL];
GDataFeedBase *feedBase = [[GDataFeedBase alloc] initWithData:data];
[tempFeedArray addObjectsFromArray:[feedBase entries]];
[feedURL release];
[feedBase release];
return tempFeedArray;
.....
I have another function where I retrieve required values from tempFeedArray object that is GDataEntryYouTubeVideo
for(int count = 0; count < loopCount; count ++){
NSMutableDictionary *feedBaseEntryDict = [[NSMutableDictionary alloc] init];
entry = [tempFeedArray objectAtIndex:count];
youTubeUrl = [[entry alternateLink] href];
if ([entry statistics]!= nil) {
noOfVws= [[[entry statistics] viewCount] intValue];
}
duratn = [[[entry mediaGroup] duration] stringValue];
descr = [[[entry mediaGroup] mediaDescription] stringValue];
authorName = [[[entry authors] objectAtIndex:0] name];
publishedDt = [[entry publishedDate] stringValue];
rating = [[[entry rating] average] stringValue];
imageURL = [[[[entry mediaGroup] mediaThumbnails] objectAtIndex:0] URLString];
videoTitle = [[[entry mediaGroup] mediaTitle] stringValue];
.....
}
......
For the first time everything works fine. But the next time, it shows memory leak at
GDataXMLNode stringFromXMLString:
Did anyone else face this issue?
I found similar issue raised in gdata developer forum:
http://groups.google.com/group/gdata-objectivec-client/browse_thread/thread/f88de5a7bb784719/cab328a8725ee6c5
but the solution doesn't solve the issue.
Any help is much appreciated.
Looks like it might not be your code but the client library there were a few other threads on the same issue. This one has a work around, but I have not tried it myself.
The other options you have would be to upgrade to latest version (1.12 was released on Apr 11th 2011), take a look at the source and try to track down your problem, or submit an issue (it looks like the project is still actively developed).
Since the code is "stealing" entries from the feed, leaving them pointing to their parent feed (rather than copying the entries, which would create independent versions) there may be an issue with the strings cache. Try disabling the cache by commenting out -addStringsCacheToDoc in GDataXMLNode.m

help on sorting NSMutableDictionary strings that are URL images

i want to populate the tablecell with title and imageurl from xml list.
i manage to store the title (NSMutableDictonary *sections )and imageURL (NSMutableDictonary *sectionsImg) into 2 NSMutableDictionary respectively.
/*******This is in viewDidLoad***/
Directory *allDirectory = [appDelegate.directories objectAtIndex:0];
for (allDirectory in appDelegate.directories)
{
NSDictionary *dica = [NSDictionary dictionaryWithObject:allDirectory.dirTitle forKey:#"dirTitle"];
NSDictionary *dico = [NSDictionary dictionaryWithObject:allDirectory.imageURL forKey:#"imageURL"];
[dirName addObject:dica];
[dirImage addObject:dico];
//NSLog(#"dic of items : %#",dirImage);
}
for (allDirectory in appDelegate.directories)
{
//retrieve the first letter from every directory title (dirTitle)
NSString * c = [allDirectory.dirTitle substringToIndex:3];
NSString * m = allDirectory.imageURL;
found = NO;
find = NO;
for (NSString *str in [self.sections allKeys])
{
if ([str isEqualToString:c])
{
found = YES;
}
}
for (NSString *stra in [self.sectionsImg allKeys])
{
if([stra isEqualToString:m])
{
find = YES;
}
}
if (!found)
{
[self.sections setValue:[[NSMutableArray alloc]init] forKey:c ];
[self.sectionsImg setValue:[[NSMutableArray alloc]init] forKey:m];
}
if (!find)
{
[self.sectionsImg setValue:[[NSMutableArray alloc]init] forKey:m];
}
}
for (NSDictionary *directory in dirName)
{
[[self.sections objectForKey:[[directory objectForKey:#"dirTitle"] substringToIndex:3]] addObject:directory];
//NSLog(#"hehehe have : %#",sections);
}
for (NSDictionary *directoryImg in dirImage)
{
//[[self.sectionsImg objectForKey:[[directoryImg objectForKey:#"imageURL"] substringFromIndex:0]] addObject:directoryImg];
[[self.sectionsImg objectForKey:[directoryImg objectForKey:#"imageURL"]] addObject:directoryImg];
//NSLog(#"HOHOHO have : %#",sectionsImg);
}
And on cellForRowAtIndexPath i declare a dictionary
NSDictionary *dictionary = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = [dictionary objectForKey:#"dirTitle"];
but when i tried to declare a dictionary for imageURL
NSDictionary *dictionaryImg = [[self.sectionsImg valueForKey:[[[self.sectionsImg allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
it gives me a error :
Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSMutableArray objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
any idea why? the logic is supposed to be the same where xml title and url can be retrieve and be displayed. Title is retrievable but imageURL is not. Help is deeply appreciated !
You are trying to sort an array... except for the fact your array isn't an array, but a NSDictionary.
Your code isn't the best at the moment. Your getting the idea of Dictionaries wrong and may be confusing them with arrays, so my best guess is your quite new to programming into objective-c.
You have two lists of things, if I'm not mistaken. The first list is the list of names, and the second list is an image corresponding with that name.
Below I'm going to do two things:
Firstly, I'm giving you two ways on how to fix your problem. It has a sample code included and gives you a small explanation with it. The possibility exist you don't understand parts of what I describe. In that case, you should;
Check out the link I described below the two solutions. It has a tutorial which makes you understand everything about arrays, dictionaries, tables and, as a bonus, XML-parsing.
So, in my opinion, you can do two things:
The first one is using an array of NSDictionaries. You'd be using a code which looks like:
NSMutableDictionary *itemOne = [[NSMutableDictionary alloc] init];
NSMutableDictionary *itemTwo = [[NSMutableDictionary alloc] init];
NSMutableArray *listOfAll = [[NSmutableArray alloc] init];
NSString *itemOneName = [[NSString alloc] initWithFormat:#"This is picture 1"];
NSString *itemTwoName = [[NSString alloc] initWithFormat:#"This is picture 2"];
NSData *imageOneData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: #"http://myurl/mypic1.jpg"]];
NSData *imageTwoData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: #"http://myurl/mypic2.jpg"]];
UIImage *itemOneImage = [UIImage imageWithData: imageOneData];
UIImage *itemTwoImage = [UIImage imageWithData: imageTwoData];
[itemOne setObject:itemOneNameString forKey:#"Name"];
[itemOne setObject:itemOneImage forKey:#"Image"];
[itemTwo setObject:itemTwoNameString forKey:#"Name"];
[itemTwo setObject:itemTwoImage forKey:#"Image"];
[listOfAll addObject:itemOne];
[listOfAll addObject:itemTwo];
Anything can be filled using that array. Just use something with a for-loop to iterate through your array.
for (int i = 0; i < [listOfAll count]; i++)
{
NSMutableDictionary *currentItem = [[NSMutableDictionary alloc] initWithDictionary:[listOfAll objectAtIndex:i]];
//Do something with that current item
}
You can also use that index in your tableView. In that case, you have to use your variable section instead of i to get your desired index.
The second one is using two arrays. Imagine you get an image named imageOne with the text imageName. Then you should use:
NSMutableArray *nameList = [[NSMutableArray alloc] init];
[nameList addObject: imageName];
NSMutableArray *imageList = [[NSMutableArray alloc] init];
[imageList addObject: imageOne];
If you want to use a certain item out of those lists, you just have to use the same indexnumber.
For example:
[theTitleLabel setText:[[NSString alloc] initWithFormat:#"%#", [nameList objectAtIndex:x]]];
[theImageView setImage:[imageList objectAtIndex:x]];
Make sure the x's are the same number.
I understand this is all a lot of information, especially if you're new to Objective - C. A tutorial exists which gives you a lot of information about how to use arrays, dictionaries and table views. As a bonus, you get to know a little about XML-parsing.
I suggest you walk through that tutorial and do everything and read everything it says. This should give you a nice start into the world of programming in iPhones.
Good luck!

Simple Way to Strip Tags In Obj-C

I am just learning objective-c and iPhone development, and I am really struggling with some very basic tasks. I am only on my 3rd day of the learning process - so that is to be expected somewhat. I'm still almost ashamed to ask such a simple question.
Anyhow, here's my question. I have a .NET web service which I call using a GET for http://somehost/ping
it returns 'pong'
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">pong</string>
The simplest of test cases.
Back on the iPhone when I retrieve the URL I have the above string as a result. I only want the 'pong' part. This seems like programming 101, but I can't seem to find a simple example of how to do it that doesn't involve defining delagates or other seemingly complex processing steps.
The problem is simple enough, find the first '>' and extract everything from there until the first '<' as an NSString. That's all I need to do.
Does anyone have a basic example of how to do this?
This is dry-coded, and kinda ugly imho. But here is a more direct answer.
NSString *xml = #"<tag>pong</tag>";
NSRange range = [xml rangeOfString:#">"];
xml = [xml substringFromIndex:range.location + 1];
range = [substring rangeOfString:#"<"];
xml = [xml substringToIndex:range.location];
Hey Sylvanaar, I'm having to do similar types of parsing inside of the client. My general methodolgy for parsing xml responses is like this. I'm pretty sure the classes are available on iphone side too. Note: it may not be the absolute best method, but it does work.
- (id)initWithXMLNode:(NSXMLNode *)node {
self = [super init];
if (self != nil) {
NSError *error;
NSArray *objects;
// Get the fingerprint
objects = [node objectsForXQuery:#"for $fingerprint in ./Fingerprint return data($fingerprint)" error:&error];
handleErrorInInit(error)
fingerprint = getFingerprint(objects);
// Get the moduleName
objects = [node objectsForXQuery:#"for $moduleName in ./Foldername return data($moduleName)" error:&error];
handleErrorInInit(error)
moduleName = getNSString(objects);
}
return self;
}
Worth showing this too. Note that NSXMLDocuments are a subclass of NSXMLNodes.
- (NSXMLDocument *)xmlDocumentFromData:(NSData *)data {
NSError *error;
NSXMLDocument *document = [[[NSXMLDocument alloc] initWithData:data options:0 error:&error] autorelease];
if (error) {
[NSApp presentError:error];
return nil;
}
return document;
}
Sometimes a full on XML parse makes sense, but a quick index/substring routine can be appropriate as well:
NSRange startBracket = [xmlFragment rangeOfString:#">"];
if(startBracket.location != NSNotFound) {
NSRange endBracket = [xmlFragment rangeOfString:#"<"
options:0
range:NSMakeRange(startBracket.location,
[xmlFragment length] - startBracket.location)];
if(endBracket.location != NSNotFound) {
NSString *value = [[xmlFragment substringFromIndex:startBracket.location+1]
substringToIndex:endBracket.location];
// Do something with value...
}
}
(Not tested, needs more error handling, yadda yadda yadda..)