iOS: How to embed a Twitter feed and/or hashtag in your app

0

One of my recent projects required a simple Twitter feed integration. Basically just a table view that showed recent tweets from either a @username or a #hashtag. No requirements to post tweets or anything like that. This seems to be a fairly common request for a lot of clients.

Being lazy, I didn’t want to sign up for an API Key or anything onerous. Someone recommended a very simple way to do this, which worked beautifully. I wanted to pass it on.

What you’ll need:

  1. JSONKit – to quickly parse the JSON.
  2. ASI – A nice simplified library for doing asynchronous HTTP requests.
  3. Google Toolbox for Mac – A useful toolkit from Google. Used for escaping HTML-style escapes.
  4. (Optional) JSONView – An extension for Chrome to very nicely format JSON.

Step 1. Find the Twitter URL
Twitter provides a really simple API that returns recent tweets in JSON format. If you do a normal search like this:

you can get back the results in JSON format by simply tweaking the URL:

If you’re using Chrome, try using JSONView to nicely visualize that. Perfect! Recent tweets about a certain theme, all in a nice machine-parseable format, no API key required. What’s more, you can use their Advanced Search GUI to tweak the query then still get back the results in JSON. Using that, I found I could combine a hashtag (#epicwinning) and a username (@charliesheen) like so:

Step 2. Set up your project
Add JSONKit and ASI to your project. This is pretty straightforward, I’m not going to walk through it. Soon we’ll see that I also needed GTM (Google Toolbox for Mac). Being a little lazy and not wanting the whole thing, I just added these two files to my project.
  • GTMNSString+HTML.h
  • GTMNSString+HTML.m

 Then I tweaked the .m file as follows to avoid external dependencies:
//#import "GTMDefines.h"
#define _GTMDevLog NSLog
#define _GTMDevAssert NSAssert
Step 3. Make the Request
Here we make a simple ASI request to fetch the recent tweets.
- (void)loadTweets
{
    // Looking for #kTwitterHashtag or @kTwitterUsername
    NSString *urlString = [[[@"http://search.twitter.com/search.json?q=%23" stringByAppendingString:(NSString *)kTwitterHashtag]
                            stringByAppendingString:@"+OR+%40"] stringByAppendingString:(NSString *)kTwitterUsername];

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlString]];
    request.delegate = self;
    [request startAsynchronous];
}
Note that Cocoa started going a little crazy when I had one big format string with things like %40 in there. I ended up breaking the string into smaller parts and appending them.

Step 3. Parse the result
When the HTTP request finishes, ASI will call your delegate method. I simply use my UITableView’s mutable array of model objects and replace its content with the “results” array contents from the JSON.
- (void)requestFinished:(ASIHTTPRequest *)aRequest
{
    NSDictionary *result = [aRequest.responseString objectFromJSONString];

    // an array of NSDictionarys with the properties
    // properties can be seen by looking at the URL with Chrome extension JSONView
    [_modelObjects removeAllObjects];
    [_modelObjects addObjectsFromArray:[result objectForKey:@"results"]];

    [self.tableView reloadData];
}
In your, -tableView:cellForRowAtIndexPath: method, just grab the key from the JSON that you wanted.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    .... // Get the cell

    NSDictionary *tweet = [_modelObjects objectAtIndex:indexPath.row];
    cell.textLabel.text = [tweet objectForKey:@"from_user"];
    cell.detailTextLabel = [[tweet objectForKey:@"text"] gtm_stringByUnescapingFromHTML];
}
Why do I use the Google Toolbox gtm_stringByUnescapingFromHTML? Because the returned JSON has things like this in it:
“I think I dislike the whole "[email protected]" phenomena”.
Those " need to be unescaped into normal quotes. This is also true for lots of other characters – ampersands, less than, greater than, etc.

Don’t forget to handle errors. In my case, I just made a fake tweet entry which said the request failed.
- (void)requestFailed:(ASIHTTPRequest *)request
{
    NSLog(@"Fetching tweets failed. Error: %@", [[request error] localizedDescription]);
    [_modelObjects removeAllObjects];

    NSDictionary *fakeErrorTweet = [NSDictionary dictionaryWithObjectsAndKeys:
                                    @"Twitter Error", @"from_user",
                                    @"Could not fetch tweets. Maybe Twitter is down?", @"text",
                                    nil];
    [_modelObjects addObject:fakeErrorTweet];
    [self.tableView reloadData];
}
Summary
That’s all there is to it. Pretty simple right?
© Copyright Force Grind - Theme by Pexeto