3 February 2010 11:00 AM
by brandontreb
iPad Programming Tutorial – Hello World++
Introduction
Now, that the iPad has been released, I’m sure you are all scrambling for ideas on how to snag a piece of the maket in the imminent gold rush. iCodeBlog is going to help you on your journey with a series of iPad tutorials to come.
Since the iPad uses the same SDK as the iPhone, all of the code under the hood is almost identical. Actually, when looking at the new and changed API classes, you will realize that most of them are user interface related. This is good news for us since we have already been coding iPhone.
While this tutorial is called “Hello World”, it is really much more than that. I assume you already have working knowledge of iPhone/Objective-C programming.
What We Will Be Creating
In today’s tutorial, I will be showing you how to create an iPad project that uses the UISplitViewController to display content in 2 separate panes. We will also be touching on some of the new design/UI patterns and giving an overall introduction to iPad programming.
The project will be based on one of my earliest tutorials that displayed a list of fruit in a UITableView and drilled down when they were selected. We will be expanding on that example and creating something that will look like this.
It uses a UISplitViewController to display a UITableView on the left and a UIView with a UIImageView subview on the right. This project is actually quite simple to create as the template code provides much of the code we need to get started.
Getting Started
1. Make sure you have downloaded the 3.2 SDK form http://developer.apple.com/iphone/. The iPad simulator will come with this download.
2. Download the resources needed for this project and unzip them iPadHelloWorldResources.zip . (contains image files and a plist we will be using to load the images)
Creating The Project
Starting a project for the iPad is no different than starting one for the iPhone. When you open XCode and select File->New Project, you should notice the addition of a Split View-Based Application. Select this and name it iPadHelloWorld.
This will create a basic application with a UITableView on the left and a UIView on the right. It will even populate the table with some sample elements. It will add the following files to your project.
Here is a brief description of each of these files:
- iPadHelloWorldAppDelegate – This is similar to every app delegate. If you look in the application:didFinishLaunchingWithOptions method, you will see that the UISplitViewController is being allocated with the MasterViewController and DetailViewControllers.
- MasterViewController – A UITableViewController, nothing fancy. It will be handling the view on the left hand side.
- DetailViewController – This handles the content view that you see on the right hand side. We will be updating this as the user selects different rows in the table to the left. This simply houses a single view.
Go ahead and press Build and Run to check out the application. If you haven’t already done so, play around with the iPad contacts and settings apps as well.
Note: When you launch the application, you will only see the main view since the simulator runs in vertical mode. To see the views side-by-side, rotate the simulator by clicking “Hardware -> Rotate Left/Right”. You can also press CMD->Arrow Left/Right on the keyboard.
Importing The Project Images
Once you have had some time to play with the new iPad project, you will now need to import the images needed for this project. After downloading and unzipping the files in from this tutorial, drag them into the project folder called “Resources-iPad”.
XCode will prompt you to copy the files, check yes and click OK.
Make sure you include all 4 images files as well as the file named fruits.plist.
Displaying The List Of Fruits
Displaying our fruits list is no different than displaying data in any other UITableView. Let’s begin by opening MasterViewController.h and adding a declaration for our fruits array.
#import @class DetailViewController;
@interface MasterViewController : UITableViewController
{ DetailViewController *detailViewController;
NSArray * fruits;
}
@property (nonatomic, retain) IBOutlet DetailViewController *detailViewController;
@property (nonatomic, retain) NSMutableArray *fruits;
@end
As you can see, there is nothing new here. We simply declare our fruits array and create a property for it.
We will be loading the fruits from the plist file that you imported into your project in the last step. Loading content from a plist file is a very quick and easy solution when you don’t require a database.
Open up MasterViewController.m and add the following line of code to your viewDidLoad method.
- (void)viewDidLoad { [super viewDidLoad]; self.fruits =
[[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:@"fruits" ofType:@"plist"]] retain];
}
The file fruits.plist is essentially an array that has been written out to a file. If you open it up, it looks very similar to XML. Now that our fruits array has been populated, let’s implement each of the UITableView delegate and datasource methods to populate the table.
UITableView datasource methods
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [fruits count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"CellIdentifier";
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Get the object to display and set the value in the cell.
cell.textLabel.text = [self.fruits objectAtIndex:indexPath.row];
return cell;
}
Nothing special… We first tell the tableview that we want fruits.count (4 in this case) number of rows.
Next, we display the name of the fruit in each tableview cell. If you want to learn more on UITableViews, read this tutorial.
UITableView delegate methods
<span style="color: #000000; font-family: Arial, Helvetica, sans-serif; white-space: normal;"><pre style="font-family: monospace;"><span style="color: #002200;"><span style="color: #000000; font-family: Arial, Helvetica, sans-serif; white-space: normal;"><pre style="font-family: monospace;"><span style="color: #002200;">- (void)tableView:(UITableView *)aTableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/* When a row is selected, set the detail view controller's detail
item to the item associated with the selected row. */
detailViewController.detailItem = [self.fruits objectAtIndex: indexPath.row];
}</span></pre>
<div><span style="color: #002200;">
</span></div>
</span></span></pre>
</span>
Here, we are simply setting the detailItem property of the detailViewController to the selected fruit. We will discuss this property later in this section, but for now all you need to know is that its type is id.
At this point, go ahead and press Build and Run to see your code in action. You should see something that looks like this:
It displays the list of fruits, but nothing happens when you select a cell (well the title of the detailView may change).
Now that we have our list of fruits displayed, we now need to implement the code to display their corresponding image.
Displaying The Fruits
Displaying the selected fruit is actually quite simple. The first thing we need to do is add a UIImageView to our detailView.
Start by adding the IBOutlet for the image view. Open up DetailViewController.h and add the following code:
@interface DetailViewController : UIViewController {
UIPopoverController *popoverController;
UINavigationBar *navigationBar; id detailItem;
IBOutlet UIImageView * fruitImageView;
}
@property (nonatomic, retain) UIPopoverController *popoverController;
@property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;
@property (nonatomic, retain) id detailItem;
@property (nonatomic, retain) IBOutlet UIImageView * fruitImageView;
@end
All of the code here comes with the template except the code to add the IBOutlet UIImageView. Once you have added this open up DetailView.xib in interface builder.
Add a UIImageView on to the view and size it to 500×500.
Now, click on the File’s Owner object and open the connection inspector (Tools -> connection inspector).
Drag from your imageView IBOutlet to the UIImageView and release. The UIImageView is now connected to your outlet.
Note: If you want the images to not skew, set the content mode of the image view (in the attributes inspector) to Aspect Fit.
Now that the imageview has been connected, it’s time to write the code that updates it. Close Interface Builder and open the file DetailViewController.m and add the following lines to the setDetailItem method:
- (void)setDetailItem:(id)newDetailItem {
if (detailItem != newDetailItem) {
[detailItem release]; detailItem = [newDetailItem retain]; // Update the view.
navigationBar.topItem.title = detailItem;
NSString * imageName = [NSString stringWithFormat:@"%@.png",detailItem];
[self.fruitImageView setImage:[UIImage imageNamed:imageName]]; }
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
}
}
Most of this code has been added by the template and I won’t discuss it too much in this tutorial. But for now, the important additions are the lines that load the image based on the name of the fruit and the one below it that sets the image property of the image view.
There you have it! Build and go and the application should function as mentioned. Here is another screenshot of the final product.
Another Cool Feature Of SplitViewController
When in vertical mode, the SplitViewController gives you another new UI element called the UIPopOverView. Collin will have a tutorial up soon on this view, but the figure below shows you what I’m talking about.
When the device is vertical, it will automatically rotate your view and provide a UIPopoverView when the “Master List” button is pretty. (BTW this button is also customizable).
You may download the source for this tutorial here iPadHelloWorld.zip.
If you have questions, post them here or ask me on Twitter.
Happy iCoding!
I am running Version 3.2.2 (Pre-release) xcode. And I notice that there is no MasterViewController.h Instead I have RootViewCOntroller.h… same for .m BUT it is a UITableVIewController.
hi, I would find it very useful if you could point out how to update the left pane with a tableview filled with parsed xml data.. this tutorial ( http://theappleblog.com/2008/08/04/tutorial-build-a-simple-rss-reader-for-iph… )shows how reading works.. but I don’t know how to get this running in the splitview.. cheers!Thomas
Hi Thomas, this post is a re-circulation from another site. I am still in the process of learning how to work with the iPad SDK as I just got my dev certification. I will post on here a new tutorial, and in fact, a few tutorials over the coming weeks as I familiarise myself with this
Hey, this is exactly what I’ve looking for for a while. Thanks. One question, though, how can we have an image appear if nothing is pressed? instead of a white screen?
Thanks. Nice tutorial.
Interesting, just curious since, there is no split view available in the iphone version, how do you find an approach that is universal?
Well, normall vievs are not universal, just the model and controllers are (depending on how you are coding). So I’d choose two different types. There are blogs out there on how to do universal, and there is a book by APress coming out later this month that will look into differences between iPad and iPhone and concurrent development.
What if you don’t want the popover view when the pad is in portrait mode (you still want a split view). Is there an easy way to do that?
i would like to ask… i want to make splitview lke this… but i dont want to use table view.. if the left part i wan use button… can this is possible?
Ok well heres my situation, i need to use a splitview controller to implement the program i want, but im wondering do i have to write every view i would ever want the program to show in the master and detail screens? heres my example i load up a log in screen that the user logs in with, then the splitcontroller is shown on the screen. After that they have a few choices to choose from in order to show a different type of detail screen, so say they choose supermarket but in supermarket you can buy milk cereal cookies ect. So does that mean in order to show the next table view i have to just reload the masters table view with all the new data i need or is their a way to push another tableView on the master screen in order to implement a navigation based tableview?To put it simplier, should i only have 2 view controllers in a splitview controller application or can i create as many view controllers as i want and just place them in the master-detail screens when needed?
I’m getting an error after UITableView datasource methods that you posted. Its requesting an identifier after period or something. The other two errors I get are from wanting identifiers as well. Help?
There is a small error in the above example code that produces an error: “RootViewController.m:16: error: type of property ‘fruits’ does not match type of ivar ‘fruits'”I changed@interface RootViewController : UITableViewController { DetailViewController *detailViewController; NSArray * fruits; }into@interface RootViewController : UITableViewController { DetailViewController *detailViewController; NSMutableArray * fruits; }to get the code to compile and work!Thanks for the tutorial!
Great tutorial, however I had trouble due to using SDK 4.2.navigationBar.topItemtitle = detailItem; threw up an error due to 4.2 auto creating toolbar rather than navigationBar. I then got the error Request for member ‘Itemtitle’ in something not a structure or union which has me stumped.
Thanks Doron, nice clear example!/paul
hi doron does SDK works on windows os..!
Ah Not sure what you mean but XCode is only available on a Mac or virtualized Mac. If suggest reading some of the books I have recommended on my site