Create a Detail View Page using UIImageView, UITextView and UILabel

tutorial019

I’m going to build this tutorial on the previous two so if you haven’t checked them out yet, you can see the first one here and the second one here. You can also download the source code on the bottom of each tutorial.

What we’ve done so far

We used UITableViewController to build out our root view controller that lists all the DVDs from our data file. Then we customized each cell by adding a DVD cover and some basic info about each movie. Tapping a row in the table caused the app to go to a detail page which was also a table displaying expanded info about the selected movie. That’s the part we’re going to work on now.

1. Download some source code to get your started

Since we’re going to be completely removing the detail view controller we used in the previous tutorials, let’s just start from there. Instead of walking you through deleting the controller and removing the appropriate functionality, download this source code that will get you started. You’ll get the root view controller with customized cells in it. However, tapping on any of the rows won’t do anything, yet. Download the primer project here: MyDVDLibrary03Primer.

2. Enhance test data file

Since our test data file only contains title, length, image and release date for each movie, that’s not going to cut it when trying to design a detail view page. We’ll at least want to add the description of the movie and maybe also its genre. This can be very tedious to do in a plist like we’re using right now but it will get a lot easier once we start using Core Data that I will cover in later tutorials.

I won’t make you add all the data by hand so for a shortcut, download the completed plist file here and replace your existing one that can be found in Xcode under the Resources folder: TestData.plist.

3. Create new DetailViewController class

In Xcode’s file browser on the left, right-click on the Classes folder and choose Add -> New File… . Under Cocoa Touch Classes group choose UIViewController subclass and make sure to check the With XIB for user interface checkbox. This will not only create our subclass but also the NIB file that we’ll use to layout our UI components.


tutorial015

4. Set up UI outlets

We now need to set up all properties in our controller that will be used on the detail view page. There will be an image view for the DVD cover, a label for the title, release date, length, genre and a text view for the description. Add this to the header file of the DetailViewController (DetailViewController.h):

@interface DetailViewController : UIViewController {
    IBOutlet UIImageView *coverImageView;
    IBOutlet UILabel *titleLabel;
    IBOutlet UILabel *releaseDateLabel;
    IBOutlet UILabel *lengthLabel;
    IBOutlet UILabel *genreLabel;
    IBOutlet UITextView *descriptionTextView;
}
 
@property (nonatomic, retain) UIImageView *coverImageView;
@property (nonatomic, retain) UILabel *titleLabel;
@property (nonatomic, retain) UILabel *releaseDateLabel;
@property (nonatomic, retain) UILabel *lengthLabel;
@property (nonatomic, retain) UILabel *genreLabel;
@property (nonatomic, retain) UITextView *descriptionTextView;
 
@end

Synthesize the properties in the implementation file (DetailViewController.m):

@synthesize coverImageView, titleLabel, releaseDateLabel, lengthLabel, genreLabel, descriptionTextView;

5. Lay out and connect UI components in Interface Builder

Before we jump to Interface Builder make sure to save all the changes so that IB can pick up on them.

In Xcode, locate DetailViewController.xib file (it got created this file along with DetailViewController class in Step#3) and double-click on it. Once Interface Builder opens you should see an empty canvas where we’re going to place our UI elements. Lay them out as shown in the screenshot below. Note that you should uncheck Editable checkbox on your text view so that the text is read-only.

tutorial016

Now we need to connect the UI elements to its variable counterparts. I’m not going to cover step-by-step how to do that as it has been discussed in some detail in the tutorial on customizing view cells. Please, review that tutorial if you’re unclear how to follow the next set of instructions.

Click on File’s Owner icon to highlight it. From the file menu choose Tools -> Connections Inspector (Cmd + 2). Under Outlets, you’ll see all of our instance variables we declared in the DetailViewController class. Control-drag from File’s Owner to each UI component in the view to connect coverImageView to Image View, releaseDateLabel to Release Date label, genreLabel to Genre label, etc. Once done, your Connections Inspector should be set up like this:

tutorial017

Save your changes and return back to Xcode.

6. Prepare DetailViewController to read test data

If you recall what we did with the original DetailViewController when it was still a table, in its initialization method we passed in a dictionary containing all the info about our DVD library. This was read in using DvdLibraryDao object that basically took the plist we constructed earlier and put all its content into a dictionary. We’re going to do the same thing in our new DetailViewController, only we’re now adding a couple of properties (genre, description) that we just added in Step#2.

We also add declaration of our custom initialization method here. It’s pretty much just a modified initWithNibName method that adds dvdData into the mix. This method will set the local instance variable dvdData that is also declared here. Change DetailViewController.h header file to look like this:

@interface DetailViewController : UIViewController {
    IBOutlet UIImageView *coverImageView;
    IBOutlet UILabel *titleLabel;
    IBOutlet UILabel *releaseDateLabel;
    IBOutlet UILabel *lengthLabel;
    IBOutlet UILabel *genreLabel;
    IBOutlet UITextView *descriptionTextView;
 
    NSDictionary *dvdData;
}
 
@property (nonatomic, retain) UIImageView *coverImageView;
@property (nonatomic, retain) UILabel *titleLabel;
@property (nonatomic, retain) UILabel *releaseDateLabel;
@property (nonatomic, retain) UILabel *lengthLabel;
@property (nonatomic, retain) UILabel *genreLabel;
@property (nonatomic, retain) UITextView *descriptionTextView;
 
- (id)initWithDvdData:(NSDictionary *)dvdData nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
 
@end

Switch over to DetailViewController.m implementation file. Let’s implement the initWithDvdData method:

- (id)initWithDvdData:(NSDictionary *)data nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        dvdData = data;
    }
    return self;
}

All this is doing is it assigns data that is passed in to our instance variable dvdData.

To read everything in from dvdData to all of the UI elements, we’ll insert a little snippet of code in the viewDidLoad delegate method. As you can see, we assign each value from dvdData to its corresponding UI element.

- (void)viewDidLoad {
    coverImageView.image = [UIImage imageNamed:[dvdData valueForKey:@"coverImage"]];
    titleLabel.text = [dvdData valueForKey:@"title"];
    releaseDateLabel.text = [NSString stringWithFormat:@"%@", [dvdData valueForKey:@"releaseDate"]];
    lengthLabel.text = [NSString stringWithFormat:@"%@ minutes", [dvdData valueForKey:@"featureLength"]];
    genreLabel.text = [dvdData valueForKey:@"genre"];
    descriptionTextView.text = [dvdData valueForKey:@"description"];
    [super viewDidLoad];
}

7. Handle didSelectRowAtIndexPath in RootViewController

Now that we have our detail view controller all ready to go, let’s connect the dots and have the RootViewController go to the detail page when a row is tapped.

In RootViewController.m, locate the didSelectRowAtIndexPath method. Just as we did before, we’ll instantiate DetailViewController here and push it to the controller stack:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    DetailViewController *controller = [[DetailViewController alloc]
                                        initWithDvdData:[dao libraryItemAtIndex:indexPath.row]
                                        nibName:@"DetailViewController" bundle:[NSBundle mainBundle]];
    controller.title = [[dao libraryItemAtIndex:indexPath.row] valueForKey:@"title"];
    [self.navigationController pushViewController:controller animated:YES];
    [controller release];
}

If everything went well, you should be able to run your project and get something like this:

tutorial018

8. Format the release date field

While something like 2007-07-08 16:32:07 -0700 is completely acceptable by me, many people want to see something a bit more user friendly. Let’s take that date and try to display it as July 8, 2007.  We’re going to achieve that using a nifty utility class called NSDateFormatter. Open DetailViewController.m and change viewDidLoad method to look like this:

- (void)viewDidLoad {
    coverImageView.image = [UIImage imageNamed:[dvdData valueForKey:@"coverImage"]];
    titleLabel.text = [dvdData valueForKey:@"title"];
    lengthLabel.text = [NSString stringWithFormat:@"%@ minutes", [dvdData valueForKey:@"featureLength"]];
    genreLabel.text = [dvdData valueForKey:@"genre"];
    descriptionTextView.text = [dvdData valueForKey:@"description"];
 
    // Format date we get from releaseDate field to more readable form
    NSDate *releaseDate = (NSDate *)[dvdData valueForKey:@"releaseDate"];
    NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
    [dateFormatter setDateFormat:@"MMMM d, YYYY"];
    releaseDateLabel.text = [dateFormatter stringFromDate:releaseDate];
 
    [super viewDidLoad];
}

All we had done is gave our formatter a string representation of the date format we want and then outputted that date to releaseDateLabel.

Conclusion

When customizing your detail views, possibilities are endless. You could add a texture to your background, add more images, maybe a table with some detailed information, or other controls that would take you forward in the controller stack. But I hope this tutorial got you started and showed you some basic techniques and tricks to create a detail page.

You can download the complete source code to this tutorial here: My DVD Library Tutorial 3

tutorial019


19 Responses to “Create a Detail View Page using UIImageView, UITextView and UILabel”

Copyright © 2009 Vladimir Olexa | Copyright © 2009 Apple Inc. | Powered by WordPress