Click here to Skip to main content
11,721,671 members (81,915 online)
Click here to Skip to main content

Making a simple Twitter app using iOS 5, Xcode 4.2, and storyboards

, 13 Jan 2012 CPOL 114.2K 4K 36
Rate this:
Please Sign up or sign in to vote.
How to use iOS 5, Xcode 4.2, and storyboards to create a simple Twitter app that will list tweets and show details about each tweet.

Download the source - 28.09 KB

Table of contents

  1. Table of contents
  2. Introduction
  3. Setting up the project
  4. The storyboard
  5. Coding the master view controller
  6. First run
  7. The segue
  8. Finishing the detail view
  9. Final run

Introduction

Let's use iOS 5, Xcode 4.2, and storyboards to make a simple Twitter app that will list tweets, and, when you click a tweet, show details about the tweet and user.

Setting up the project

In Xcode, start by creating a new project from FileNewNew Project.

Select Master-Detail Application and click Next.

As Product Name enter 'Twitter Test'. Make sure the Use Storyboard and Use Automatic Reference Counting check boxes are checked. Click Next.

Select where to save the project and click Create.

Your project is now created. It has automatically set up a storyboard a master view controller and a detail view controller. The storyboard is where we will design our app – the controllers are where the programming takes place.

The storyboard

Let's open up our storyboard to see what it contains. Click on MainStoryboard.storyboard to the left and the storyboard comes up:

This basically tells us that we have:

  1. A navigation view controller – that's the type of controller that automatically gives a Back button when you navigate from a list view down to a detail view.
  2. A master view controller – that's where we'll have our tweet list.
  3. A the detail view controller – that's where we'll have details about each tweet.

The lines between each controller are called 'segues'. We'll talk more about these later on when we handle the action when the user selects a tweet.

Let's set up our table view.

Setting up the table view

Select the table view in the tree view to the left:

And to the right select Dynamic Prototypes:

This tells the table view that we're going to set up the cells dynamically from our controller.

Next, again in the tree view to the left, select the Table View Cell:

And, on the right, set style to Subtitle and Identifier to 'TweetCell' – that's the name we're going to use in our code to find the cell so we can fill out its details:

You'll see that the view style changes – that's the style we'll use to display the tweet text as the title, and tweet author as the subtitle:

So, now we're all set up in the storyboard part – at least as far as the master view goes. Don't worry – we'll get back to the detail view later on.

Moving on to the controller.

Coding the master view controller

Go into MasterViewController.m by selecting it on the left:

This is where all the action will take place. But first we need to set up an instance variable to contain our tweets.

Click on MasterViewController.h to the left:

And replace the @interface to @end part with the following code:

@interface MasterViewController : UITableViewController {
    NSArray *tweets;
}

- (void)fetchTweets;

@end

This tells Objective-C that we have a tweets instance variable and a fetchTweets method.

Loading the JSON

Now to the actual tweet fetching. Go back into MasterViewController.m and insert the following method:

- (void)fetchTweets
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData* data = [NSData dataWithContentsOfURL:
                        [NSURL URLWithString: @"https://api.twitter.com/1/statuses/public_timeline.json"]];

        NSError* error;

        tweets = [NSJSONSerialization JSONObjectWithData:data
                                                 options:kNilOptions
                                                   error:&error];

        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadData];
        });
    });
}

What this does is that it makes a separate thread to fetch the JSON data and then goes back to the main thread to update the table view when it's done. The reason to do this is that if we were to get the data using the main thread, then the application would lock up until the data was loaded.

Call this method from inside the viewDidLoad method:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self fetchTweets];
}

This tells the application to load the JSON data as soon as the view loads.

So now our Twitter feed is loaded into to our instance variable named tweets. This now contains an array holding a number of NSDictionary objects where NSDictionary is a key/value collection.

Filling the table view

Next, insert the following two methods:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return tweets.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TweetCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];
    NSString *text = [tweet objectForKey:@"text"];
    NSString *name = [[tweet objectForKey:@"user"] objectForKey:@"name"];

    cell.textLabel.text = text;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"by %@", name];

    return cell;
}

First run

Try running your application – click the Run icon:

And it works:

Pretty simple, huh? Smile | :)

Well, can't dwell on our success, so let's go on to something that needs to be done.

The segue

Try selecting a tweet. Our intention was to load the detail view, but this doesn't happen. Why not?

Let's go back into the storyboard:

Notice how there's no segue between the master view controller and the detail view controller. What happened was that when we went from static cells to prototype cells in the storyboard before, it erased it, so now it doesn't know what to do. Let's help it out.

Setting up the segue

To the left, CTRL + drag from the Table View Cell to Detail View Controller, and select Push:

Now it knows what to do, so try hitting Run again.

And it works.

Click on the segue between the table view and detail view:

And change its identifier to 'showTweet':

That's how we're going to identify it later in the following code.

Responding to the segue

In MasterViewController.m, right below #import "MasterViewController.h", insert the following code:

#import "DetailViewController.h"
 

This is to give us access to the detail view controller from the master view controller.

Insert the following method:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"showTweet"]) {

        NSInteger row = [[self tableView].indexPathForSelectedRow row];
        NSDictionary *tweet = [tweets objectAtIndex:row];

        DetailViewController *detailController = segue.destinationViewController;
        detailController.detailItem = tweet;
    }
}

Basically what this does is that it tells the app what to do when it hits the segue between the master view and the detail view. It identifies the selected row, finds the tweet, and then sets the detailItem property on the detail view controller. (The detailItem property was automatically created when we selected Master-Detail Application in the beginning. Thanks Xcode!)

Now we're ready to do the detail view controller.

Finishing the detail view

Open up the storyboard and double click on the 'Master' and 'Detail' titles and change them to 'Tweets' and 'Tweet' accordingly:

Delete the label saying 'Detail view content goes here'. We'll be creating our own.

Insert a label for the name, a label for the tweet, and an image view for the profile image, like this:

You can customize the text sizes like you want.

Creating outlets for the detail view

We'll need a way to call these new controls from our code. This is done by creating three outlets which is a sort of wire, or connection, between the view and the controller. In DetailViewController.h, replace the @interface line with the following code:

@interface DetailViewController : UIViewController {
    IBOutlet UIImageView *profileImage;
    IBOutlet UILabel *nameLabel;
    IBOutlet UILabel *tweetLabel;
}

Now we have created the outlets. We now need to reference, or connect, these from our views. To the left, CTRL + drag from Detail View Controller to 'Label – Name goes here' and select nameLabel:

CTRL + drag also from Detail View Controller to 'Label – Tweet goes here' and select tweetLabel, and from Detail View Controller to 'Image View' and select profileImage.

Now we can call the labels and image view from our code.

Loading the detail view

In DetailViewController.m, replace the configureView method with the following code:

- (void)configureView
{
    if (self.detailItem) {
        NSDictionary *tweet = self.detailItem;

        NSString *text = [[tweet objectForKey:@"user"] objectForKey:@"name"];
        NSString *name = [tweet objectForKey:@"text"];

        tweetLabel.lineBreakMode = UILineBreakModeWordWrap;
        tweetLabel.numberOfLines = 0;

        nameLabel.text = text;
        tweetLabel.text = name;

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSString *imageUrl = [[tweet objectForKey:@"user"] objectForKey:@"profile_image_url"];
            NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];

            dispatch_async(dispatch_get_main_queue(), ^{
                profileImage.image = [UIImage imageWithData:data];
            });
        });
    }
}

Final run

Try running the code, and there you have it – a list view and a detail view showing the tweet!

Hope you liked it Smile | :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

lassebunk
Denmark Denmark
Lasse is a long-time programmer, having more than 20 years of programming experience and more than 15 years of experience programming for the world wide web. He writes articles about Ruby on Rails, programming, SEO, and, recently, iOS programming.

You may also be interested in...

Comments and Discussions

 
Questioncreate a rss feed for website apk Pin
Member 1171232022-May-15 11:25
memberMember 1171232022-May-15 11:25 
GeneralMy vote of 4 Pin
KarstenK4-Nov-14 22:06
memberKarstenK4-Nov-14 22:06 
Questionenable to click the url Pin
alayoup29-Oct-13 13:51
memberalayoup29-Oct-13 13:51 
QuestionData parameter is nil Pin
zairy123454-Dec-12 20:50
memberzairy123454-Dec-12 20:50 
AnswerRe: Data parameter is nil Pin
Member 979651429-Jan-13 19:41
memberMember 979651429-Jan-13 19:41 
GeneralRe: Data parameter is nil Pin
Daniel Sadjadian20-Jun-13 9:31
memberDaniel Sadjadian20-Jun-13 9:31 
QuestionAPI is out of order Pin
vrutti5-Nov-12 19:13
membervrutti5-Nov-12 19:13 
Nice Tutorials Smile | :)

But the API which contains JSON is out of order.. :(
AnswerRe: API is out of order Pin
Seth-B31-Jan-13 10:18
memberSeth-B31-Jan-13 10:18 
GeneralRe: API is out of order Pin
Member 102569596-Sep-13 4:33
memberMember 102569596-Sep-13 4:33 
Question"Duplicate declaration of method 'tableView:numberOfRowsInSection:' Pin
Robert A Wilson8-Oct-12 3:32
memberRobert A Wilson8-Oct-12 3:32 
QuestionButtons Pin
techd845-Sep-12 6:48
membertechd845-Sep-12 6:48 
QuestionMakeing this a universal app Pin
techd8417-Aug-12 23:59
membertechd8417-Aug-12 23:59 
Answerjson Pin
mr_Chris1-Aug-12 16:36
membermr_Chris1-Aug-12 16:36 
QuestionApp crashes with another JSON Feed Pin
Member 927109417-Jul-12 23:16
memberMember 927109417-Jul-12 23:16 
AnswerRe: App crashes with another JSON Feed Pin
phamthanhnhan141-Apr-13 8:28
memberphamthanhnhan141-Apr-13 8:28 
QuestionMaking a simple Twitter app using iOS 5, Xcode 4.2, and storyboards Pin
chamara2k21-May-12 15:08
memberchamara2k21-May-12 15:08 
QuestionFriends tweets Pin
Member 89338185-May-12 18:33
memberMember 89338185-May-12 18:33 
QuestionReTweet function? Pin
DannyBribiesca4-May-12 16:42
memberDannyBribiesca4-May-12 16:42 
QuestionTimestamp Pin
Stewart Crainie25-Mar-12 3:43
memberStewart Crainie25-Mar-12 3:43 
AnswerRe: Timestamp Pin
techd847-Sep-12 12:28
membertechd847-Sep-12 12:28 
QuestionConversion Array to String? Pin
Member 822280517-Feb-12 11:26
memberMember 822280517-Feb-12 11:26 
Question.json Pin
Member 822280514-Feb-12 11:29
memberMember 822280514-Feb-12 11:29 
AnswerRe: .json Pin
lassebunk14-Feb-12 11:44
memberlassebunk14-Feb-12 11:44 
GeneralRe: .json Pin
Member 822280515-Feb-12 11:26
memberMember 822280515-Feb-12 11:26 
GeneralRe: .json Pin
lassebunk15-Feb-12 11:28
memberlassebunk15-Feb-12 11:28 
GeneralRe: .json Pin
Member 822280517-Feb-12 5:09
memberMember 822280517-Feb-12 5:09 
GeneralRe: .json Pin
lassebunk17-Feb-12 5:11
memberlassebunk17-Feb-12 5:11 
GeneralRe: .json Pin
Member 822280517-Feb-12 5:22
memberMember 822280517-Feb-12 5:22 
GeneralRe: .json Pin
lassebunk17-Feb-12 5:26
memberlassebunk17-Feb-12 5:26 
GeneralRe: .json Pin
Member 822280517-Feb-12 6:10
memberMember 822280517-Feb-12 6:10 
GeneralRe: .json Pin
KarstenK8-Jan-14 3:43
memberKarstenK8-Jan-14 3:43 
GeneralMy vote of 4 Pin
Member 822280514-Feb-12 11:18
memberMember 822280514-Feb-12 11:18 
QuestionCant change Identifier in Table View Cell Pin
Bikeaccdnt20-Jan-12 14:12
memberBikeaccdnt20-Jan-12 14:12 
AnswerRe: Cant change Identifier in Table View Cell Pin
lassebunk24-Jan-12 1:08
memberlassebunk24-Jan-12 1:08 
Questiontypo Pin
kartone13-Jan-12 8:40
memberkartone13-Jan-12 8:40 
AnswerRe: typo Pin
lassebunk13-Jan-12 13:48
memberlassebunk13-Jan-12 13:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150901.1 | Last Updated 13 Jan 2012
Article Copyright 2012 by lassebunk
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid