Adding a UITableView to a custom UIViewController

On my last tutorial post I demonstrated how one would add a UIToolbar to a UITableViewController for the case where you would want a UITableViewController to be the main view, rather than embedding a UITableView in a custom UIViewController.

I will now explain how to do the opposite, which is embedding a UITableView in your own custom view (for showing lists or options, or dynamically updated data). I will go through creating the UIView, and adding hooks to a UITableView inside our new custom view.

In my case, I needed to add a “Recent Searches” table on a custom view that had a search bar. Rather than using the one given by Interface Builder, lets build our own to learn how to do this.

First, create a UIViewController by adding a new file. Make sure that when creating it, the UITableViewController checkbox is NOT on, and that the “Create XIB for user interface” checkbox IS on. This will create the .m, the .h and the XIB files.

Lets start off by creating our outlets in the .h file to create our hooks for the search bar and the table view:

@interface EmbeddedTableView : UIViewController {
     IBOutlet UISearchBar* search;
     IBOutlet UITableView* recentSearchesTable;
}

@property (nonatomic, retain) UISearchBar* search;
@property (nonatomic, retain) UITableView* recentSearchesTable;

@end

Since we’re going to be implementing the UITableView callbacks, we need to implement a couple of delegates, so change the @interface line to look like the following:

@interface EmbeddedTableView : UIViewController <UITableViewDelegate, UITableViewDataSource>  {

Dont forget to synthesize the search bar and the table in your class file’s .m:

@implementation EmbeddedTableView

@synthesize search;
@synthesize recentSearchesTable;
...

OK, now on to the interface. Double-click the XIB file in XCode to open up Interface Builder.

You should now see the View hierarchy and an empty view window. Go ahead and drag a Search Bar (UISearchBar) onto the top of the empty View. We should have the following at this point:

We’re going to leave the hook for the UISearchBar for another tutorial as it would complicate things slightly and deviate from the subject of this post. So let’s go ahead and add the UITableView to the view we’ve created. Drag a TableView to our view with the search bar. Let it expand to fill the empty area. We should now have the following:

Next, open up the inspector for the TableView so we can connect the outlets. If the Inspector is open, it is the 2nd tab, otherwise go to Tools->Connections Inspector (Command-2).

We want to drag the + button to the File’s Owner element in our hierarchy for the 2 Outlet items (dataSource, delegate) and do the same for the Referencing Outlet. When you let go of the button on the File’s Owner for this last item, it should give you the option to choose the recentSearchesTable. The inspector should look like this now:

Now, finally time to start writing some code! Save the XIB, and lets go back to XCode. If you want to connect the SearchBar, follow the same process as above. Since we’ve set up the outlet for the SearchBar, when you go to connect the Referencing Outlet, you should have the option to pick the ‘search’ outlet which we defined previously to be our UISearchBar.

We now have the basics set up. We have our Outlets connected to the interface objects, we have set up our delegate declarations, and now its time to write the implementation.

In your source .m file, we need to add our table delegate and dataSource callbacks:

#pragma mark Table view methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	return 5;
}

// Customize the appearance of table view cells.
- (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];
    }

    // Set up the cell...
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:15];
    cell.textLabel.text = [NSString	 stringWithFormat:@"Cell Row #%d", [indexPath row]];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	// open a alert with an OK and cancel button
	NSString *alertString = [NSString stringWithFormat:@"Clicked on row #%d", [indexPath row]];
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertString message:@"" delegate:self cancelButtonTitle:@"Done" otherButtonTitles:nil];
	[alert show];
	[alert release];
}

That’s pretty much it. If you had started with a Window Based app, it would be necessary to add a couple things in your App Delegate. Your ApplicationDidFinishLaunching should look like the following:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after app launch    

	UINavigationController* navController = [[UINavigationController alloc] init];
	EmbeddedTableView* tView = [[EmbeddedTableView alloc] initWithNibName:@"EmbeddedTableView" bundle:[NSBundle mainBundle]];
	[navController pushViewController:tView animated:YES];
	[tView release];

	[window addSubview:navController.view];
	[window makeKeyAndVisible];

}

And we should add a title to our Table View class:

- (void)viewDidLoad {
    self.title = @"Search";
    [super viewDidLoad];
}

Compile, run and you should have the following as your first view:

Clicking on one of the items should bring up an alert like we designed it to do:

NOTE: In the sample project, I’ve used a text view in place of the search bar. This way you can get a feel for how you can have multiple types of views embedded in a single controller.

Here is a link to the sample project: TableViewTut



Beginning iOS 5 Development: Exploring the iOS SDK (Paperback)

By (author): David Mark, Jack Nutting, Jeff LaMarche

The team that brought you the bestselling Beginning iPhone 4 Development is back again for Beginning iOS 5 Development, bringing this definitive guide up-to-date with Apple's latest and greatest iOS SDK, as well as with the latest version of Xcode. 

There's coverage of brand new technologies, with chapters on storyboards and iCloud, for example, as well as significant updates to existing chapters to bring them in line with all the changes that came with the iOS 5 SDK. You'll have everything you need to create your very own apps for the latest iOS devices, including the iPhone 4S, iPad 2, and the latest iPod touch. Every single sample program in the book has been rebuilt from scratch using Xcode 4.2 and the latest iOS 5-specific project templates and designed to take advantage of the latest Xcode features.

Assuming only a minimal working knowledge of Objective-C, and written in a friendly, easy-to-follow style, Beginning iOS 5 Development offers a complete soup-to-nuts course in iPhone, iPad, and iPod touch programming. The book starts with the basics, walking through the process of downloading and installing Xcode and the iOS 5 SDK, and then guides you though the creation of your first simple application.

From there, you’ll learn how to integrate all the interface elements Apple touch users have come to know and love, such as buttons, switches, pickers, toolbars, and sliders. You’ll master a variety of design patterns, from the simplest single view to complex hierarchical drill-downs. The confusing art of table building will be demystified, and you’ll learn how to save your data using the iPhone file system. You’ll also learn how to save and retrieve your data using a variety of persistence techniques, including Core Data and SQLite. And there’s much more! You’ll learn to draw using Quartz 2D and OpenGL ES, add multitouch gestural support (pinches and swipes) to your applications, and work with the camera, photo library, accelerometer, and built-in GPS. You’ll discover the fine points of application preferences and learn how to localize your apps for multiple languages.

  • The iOS 5 update to the bestselling and most recommended book for Cocoa touch developers
  • Packed full of tricks, techniques, and enthusiasm for the new SDK from a developer perspective
  • Written in an accessible, easy-to-follow style

What you’ll learn

  • Everything you need to know to develop your own bestselling iPhone and iPad apps
  • Best practices for optimizing your code and delivering great user experiences
  • How to create “universal” apps for both the iPhone and iPad
  • What is data persistence and why is it important
  • Get started with building cool, crisp User Interfaces
  • What and how to use Table Views
  • How to do graphics with Quartz and OpenGL ES
  • What geo app development features the new iOS 5 brings to the iPhone 4S
  • How to get your app in iCloud
  • And much much more...

Who this book is for

Everyone who wants to start developing for iPhone, iPod touch, and iPad!

For the latest sourcecode, please head to www.iphonedevbook.com.

Table of Contents

  1. Welcome to the Jungle
  2. Appeasing the Tiki Gods
  3. Handling Basic Interaction
  4. More User Interface Fun
  5. Autorotation and Autosizing
  6. Multiview Applications
  7. Tab Bars and Pickers
  8. Introduction to Table Views
  9. Navigation Controllers and Table Views
  10. Storyboards
  11. iPad Considerations
  12. Application Settings and User Defaults
  13. Basic Data Persistence
  14. Get Your App in the iCloud
  15. Grand Central Dispatch, Background Processing, and You
  16. Drawing with Quartz and OpenGL
  17. Taps, Touches, and Gestures
  18. Where Am I? Finding Your Way with Core Location
  19. Whee! Gyro and Accelerometer!
  20. iPhone Camera and Photo Library
  21. Application Localization
  22. Where to Next?
List Price: $39.99 USD
New From: $2.09 USD In Stock
Used from: $0.01 USD In Stock

  • Pingback: Aboveground Systems

  • Pingback: KD Munoz

  • jcp

    Thank you for this cool tutorial – this was exactly what saved my day!!!

  • jcp

    Thank you for this cool tutorial – this was exactly what saved my day!!!

  • http://none jeff

    i have a problem with the uitableview using tableviewcontroller. it occupies all the width and height of the view when scrolling. is there a way to fix the height and width of the tableview.

    thanks

  • James Ccy

    Thx you,
    I am trying to follow your tutorial, but it seems that I’ve missed something.
    I am hoping you can provide a link to download entire source.

  • http://www.aboveground.com AbovegroundDan

    I’ll try to get the project uploaded in the next day or so.

  • saxone

    thanks a lot for your perfect tutorial :)

  • Bas Holtrop

    Thanks for explaining, this was a real timesaver :-)

    One remark though, shouldn’t the interface definition of your EmbeddedTableView say that it implements the UITableViewDelegate protocol? Like this:

    @interface EmbeddedTableView : UIViewController

    Your example works with and without the UITableViewDelegate interface definition though.

  • Bas Holtrop

    Hm, I see the less-than and greater-than characters in my code sample cause some html trouble, but I think you get the idea :-)

  • http://www.aboveground.com AbovegroundDan

    Hmm, you’re probably right. And along with the UITableViewDelegate protocol should be the UITableViewDataSource protocol as well.

    I dont recall the compiler complaining (warning) about it so maybe Interface Builder does some magic in the XIB’s to prevent that. Or, my memory is failing me and it did warn about it, and I chose to blissfully ignore it :)

  • talbot

    Simple and efficient. Thanks!

  • Novato

    Thankyou very much it’s what i need!!!

  • Test

    Thanks for the tutorial but where can I find the second part?

  • Lachlan Scott

    I found this post very well written, focused and helpful, thank you!

    I also noticed the interface line didn’t seem quite right, and was interested to read that it worked fine. Presumably, because we make the connection between the table view and their data source in the XIB. I changed 

    interface EmbeddedTableView : UIViewController { 

    to
    interface EmbeddedTableView : UITableViewController { 

    but presumably we could also simply add the TableView protocol references as 
    Bas Holtrop suggested, like so

    interface EmbeddedTableView : UITableViewController { 

    Can you give us an explanation of which is preferred and why?

  • AbovegroundDan

    You don’t want to inherit from UITableViewController. What we want is to embed a UITableView in a UIViewController, so that we have the option of adding other views to it without having to work around the TableViewController, which was just meant to house a table view.

    The reason that you really don’t have to reference the DataSource and Delegate in the interface definition is precisely what you said, we are making those connections through IB. 

    That of course, brings up a discussion of whether its best to use IB rather than code to do the same. For easier portability between projects I prefer the code route, but I tried to gear this particular tutorial towards the beginner, who may be using IB to define their views rather than code.

    I’ve fallen behind on tutorials, unfortunately, due to crazy workloads, but will try to do some in the near future. I take requests, so please let me know what you all would like to see.

     -Dan

  • http://www.aboveground.com AbovegroundDan

    You don’t want to inherit from UITableViewController. What we want is to embed a UITableView in a UIViewController, so that we have the option of adding other views to it without having to work around the TableViewController, which was just meant to house a table view.

    The reason that you really don’t have to reference the DataSource and Delegate in the interface definition is precisely what you said, we are making those connections through IB. 

    That of course, brings up a discussion of whether its best to use IB rather than code to do the same. For easier portability between projects I prefer the code route, but I tried to gear this particular tutorial towards the beginner, who may be using IB to define their views rather than code.

    I’ve fallen behind on tutorials, unfortunately, due to crazy workloads, but will try to do some in the near future. I take requests, so please let me know what you all would like to see.

     -Dan

  • spe1083

    Were you able to upload the project?

  • http://www.aboveground.com AbovegroundDan

    I realized I hadn’t, and that project is long lost, so I created a new one just now. Instead of the search bar I used a scrolling text view so you can get a feel for custom views being built up from other views. It’s not hooked up, but its a simple matter to do so. I was going to hook up the table view to control a web view, but it would have complicated things, so I didn’t want to confuse anyone with that.

    The new project is linked at the bottom of the post.

  • http://www.aboveground.com AbovegroundDan

    Actually, I’m thinking now that it may have been a posting error that the datasource and delegate declarations had disappeared. I just tried to edit it and due to the less-than and greater-than signs, the HTML filter removed them. I edited with the equivalent symbols and now they are properly showing up.

  • Michaelgeekz

    You are the greatest person ever!!!!!! You saved my life I’ve been at this for 3 hours straight its 4am…now I can sleep in peace :D!!!!!

  • http://www.facebook.com/joao.p.nunes João Nunes

    Great! I was looking for this!

  • http://twitter.com/waynewbishop Wayne Bishop

    Wonderful article! Worked like a charm.  Thanks!

  • hzhou81

    Very good article,but i have an another question.
    when I alloc an NSMutableArray in EmbeddedTableView.h file
    (and with synthesize in EmbeddedTableView.m file)
    I can access this NSMutableArray in EmbeddedTableView.m’s -(void)viewDidLoad method,
    but i CANNOT access this NSMutableArray in EmbeddedTableView.m’s ”-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section”  this method!??

    Please help!

  • http://www.aboveground.com AbovegroundDan

    Make sure you’re properly declaring the variable, and try accessing it with self.myArray in the tableView delegate methods.

  • hzhou81

    Thanks again,but it does not work.Either access it with variable name nor self.variable worked.
    you can try this:
    1st. after “@ property (nonatomic, retain) UITableView* recentSearchesTable;” declare a variable like this
    “@ property (nonatomic,retain) NSString *testName;”
    2nd. after “@ synthesize recentSearchesTable;” synthesize the variable testName like this ” @ synthesize testName;”
    3rd. In .m’s - (void)viewDidLoad method,just give the NSString a content like this [testName=@ "hi"];
    4th. In .m’s numberOfRowsInSection method,add following 
    UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:@”title” message:self.testName delegate:self cancelButtonTitle:@”OK” otherButtonTitles:nil, nil];
        [alertView show];
    it doesn’t show the value “hi” of testName variable!!
    Please help again!!

  • http://www.aboveground.com AbovegroundDan

    You’re setting testName incorrectly. Either use: testName = @”Hi”;  or call the accessor method: [self setTestName: @"Hi"];

  • hzhou81

    Thank you for your patient!
    but your [self setTestName:@"Hi"]; still doesn’t work. 
    I have tested the value after I setter the value in “viewDidLoad()”,it shows “Hi”
    but value lost in numberOfRowsInSection method.
    I promiss strange thing happened to me!

  • http://www.aboveground.com AbovegroundDan

    Not sure exactly what you’re doing, but here’s the sample code with a test string like you’re trying to do: http://www.aboveground.com/wp-content/uploads/2012/06/TableViewTut2.zip

  • Marcio Viegas

    im trying to redirect to another controller when i select a cell but something is wrong. Instead of the alarm i want to redirect to another controller. How can i do that

  • Pingback: Georges Stephan

  • Elga

    Thank you for this article, is was very useful for me. My embedded table view is showing the data OK. But I have another problem: in my embedded table view, the reloadData method is not working.

    My table view should exibit an item of an array of dictionaries and there are two buttons for going backward and forward in the array. It starts with the first item, that is shown OK, but when the IBActions call the reloadData method in order to refresh the table content, nothing happens.

    I tried all my code in a “classic” UITableViewController and it works fine, so, I think my logic is correct. It is like some kind of linking was missing in the case of embedded table view.
    Any sugestion?

    Thanks,

    Elga.

  • Elga

    Well, I downloaded your project and add a button to force the reload of table. It works OK.
    Then I analized your code, looking for some essential difference with mine, and I discovered that I was calling “alloc + init” for my table control in viewDidLoad method. It probably was erasing all the configurations and linkings made by IB!

    I deleted this line and now reloadData is working perfectly.
    Thanks a lot!
    Elga.

  • http://www.aboveground.com AbovegroundDan

    Glad you got it working! Thanks for the kind words.

  • Julio Marroquin

    I’m trying to implement this on a Master/Detail view but I get a blank table. I’m thinking the appDelegate part must be different for this kind of view? Any suggestions?

  • Julio Marroquin

    Nevermind, I solved it. I had to give the Identifier field for the prototype cell on the storyboard the same name as the Reusable Cell Identifier I used on cellForRowAtIndexPath.

  • Nik

    Thank you! Simple & fast!

  • sergej

    next time plz mark clearly what code should be in which file!

  • siva

    how to apply animation in the tableviewcell

  • http://www.aboveground.com AbovegroundDan

    It’s pretty clear in the descriptions where I mention ‘add this to your .m’ or ‘put this in the .h file’.

  • http://www.aboveground.com AbovegroundDan

    What kind of animation?

  • http://www.aboveground.com AbovegroundDan

    Implement a delegate for the action, and have the didSelectRow method call the delegate.

  • ekke

    Excellent, it worked immediately! Thankyou!

  • Lyndon

    Muchos gracias! This tutorial saved me a lot of time in quickly inserting a table view into a view!

  • Arturo

    hello

    I am new to xcode and I’m trying to follow the tutorial, I have a question, you must be working all within the UIViewController or within a tableviewcontroller?

  • http://www.aboveground.com AbovegroundDan

    It’s a UIViewController. The whole point of this tutorial is to be able to use a UITableView inside of a UIViewController so that you are not limited to the things provided by UITableViewController.