How To Make An Interface With Horizontal Tables Like The Pulse News App: Part 1
This is a blog post by iOS Tutorial Team member Felipe Laso, an independent iOS developer and aspiring game designer/programmer. In this 2-part series you’ll learn how to make an interface similar to the Pulse News app for iPhone and iPad by using only UITableViews. Here are some of the things we’ll focus on for […] By Ray Wenderlich.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How To Make An Interface With Horizontal Tables Like The Pulse News App: Part 1
40 mins
Repeating The Process For iPad
We have our vertical table view working properly on iPhone but not on iPad (you can run the project in the iPad simulator to see this).
Just to remember the steps we must follow in order for things to work on iPad:
- Create a subclass of ArticleListViewController named ArticleListViewController_iPad (make sure you create an XIB interface for this class and target it for iPad)
- Import “ArticleListViewController.h” at the top of “ArticleListViewController_iPad.h”
- Cleanup the methods we don’t need inside the ArticleListViewController_iPad.m file
- Add the cellForRowAtIndexPath method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = @"Vertical Table Rows on iPad";
return cell;
}
- Delete the View in the ArticleListViewController_iPad.xib NIB file
- Add a Table View to the NIB file
- Connect the File’s Owner View outlet to the Table View
- In the MainWindow_iPad.xib file select the Navigation Controller’s Root View Controller and change its class to ArticleListViewController_iPad in the Identity Inspector
- In the Attributes Inspector put ArticleListViewController_iPad as the NIB name for the Root View Controller
Go ahead and run the project in the iPad simulator (or an actual iPad device) and this is what you’ll get:
Not very interesting, I know! Specially since we can’t select rows or have anything particularly interesting going on with the interface. These are crucial steps as they will serve as the foundation for our highly customized UI later on, getting them right is just as important as the rest of the project.
Loading Articles Into Our Application
Our project is well on it’s way to being a cool looking app, but what good will it be if we don’t have any images or articles to actually display?
We’ll be loading the information we need off a property list file that we store in our application bundle. If you would like to load an RSS feed then check out the How To Make A Simple RSS Reader iPhone App tutorial available on this site.
I have created a simple property list made up of dictionary as the root object which contains seven arrays with a key (we will use this key as the category title). Each one of these seven arrays contains ten dictionaries that store the title, category and image name for our articles.
Go ahead and download the resources for this project, which includes the property list as well as the images we’ll need.
By now you should be comfortable creating folders within Xcode so go ahead and make a new one called Resources. Drag the Articles.plist and Article Images folder into this Resources group, make sure that “Copy items into destination group’s folder (if needed)” is checked, and click Finish.
Now that we have the property list in our project let’s load up the info and put it in our table to verify it’s working.
Back in our ArticleListViewController.h file let’s add an NSDictionary ivar as well as a property for it. Modify ArticleListViewController.h to look like the following:
#import <UIKit/UIKit.h>
@interface ArticleListViewController : UITableViewController
{
NSDictionary *_articleDictionary;
}
@property (nonatomic, retain) NSDictionary *articleDictionary;
@end
Let’s go ahead and synthesize our property adding the following line just after the implementation and set the property to nil in the viewDidUnload method:
@synthesize articleDictionary = _articleDictionary;
- (void)viewDidUnload
{
[super viewDidUnload];
self.articleDictionary = nil;
}
Now what we want to do in our viewDidLoad method is load up our dictionary with the contents of the property list, this is actually very simple. Make the following change to your viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.articleDictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Articles" ofType:@"plist"]];
}
Before running our project let’s display the info on the table view we have. Still within our ArticleListViewController.m file go ahead and change the numberOfSectionsInTableview method and the numberOfRowsInSection method as follows:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.articleDictionary.allKeys count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
NSArray* sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSString *categoryName = [sortedCategories objectAtIndex:section];
NSArray *currentCategory = [self.articleDictionary objectForKey:categoryName];
return [currentCategory count];
}
You might be wondering why we use a sort descriptor to sort the array of keys we have. That’s because if you take a look at the property list file, before each category name there is a number. Since this is an NSDictionary, the categories will load up in different orders and I want them to show up in a specific order, specially the headlines which should be the first category
All you are doing here is creating a sort descriptor which will sort the objects in ascending order (from 1-7). When we set the title for each section we are gonna have to do some work with strings in order to remove that first character.
Another workaround would be making our dictionary be contained within an array in the property list, that way each item is located in a specific position and loaded in the same order, for our case that would be a bit overkill as removing the number is a one line process.
Let’s now get the titles for our sections by adding the method below:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
NSArray* sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSString *categoryName = [sortedCategories objectAtIndex:section];
return [categoryName substringFromIndex:1];
}
We follow the same process of sorting our keys and getting the current category title depending on the section we are in. Finally all we do before returning the string with the category name is to get a substring starting from the first index (the number is located at index 0, which is where our string indexes begin).
Go ahead and build and run the project either on the iPhone or iPad simulator and this is what you’ll get:
It’s working! And it loads up in the order specified which is just what we wanted :D
But we are still using that placeholder text for our rows, let’s go ahead and fix that. In order to do this we are going to have to change the cellForRowAtIndexPath method in both our ArticleListViewController_iPhone.m and ArticleListViewController_iPad.m files.
Right now the changes we will make are identical, which seems kind of pointless, but later on when we have custom table cells for each device, having specific view controllers will come in handy.
Open up ArticleListViewController_iPhone.m and make these changes to the cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
NSArray* sortedCategories = [self.articleDictionary.allKeys sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSString *categoryName = [sortedCategories objectAtIndex:indexPath.section];
NSArray *currentCategory = [self.articleDictionary objectForKey:categoryName];
NSDictionary *currentArticle = [currentCategory objectAtIndex:indexPath.row];
cell.textLabel.text = [currentArticle objectForKey:@"Title"];
cell.imageView.image = [UIImage imageNamed:[currentArticle objectForKey:@"ImageName"]];
return cell;
}
The keys we are using in order to get the title and image name for our article are not random, open up the Articles.plist file and you will see that those are the keys we used when creating the dictionaries. You could have used whatever you liked, or perhaps create definitions for these keys so they are not hard coded into our method, but for now this will do as we do no intend to change the names.
Make these changes to the cellForRowAtIndexPath method in the ArticleListViewController_iPad.m file as well and go ahead and run your project on either device.
This is what the project looks like on both iPhone and iPad:
Already it’s looking quite good, don’t you think?