Tuesday, October 23, 2012

Adding a UITableView Tutorial

For beginners, this is one of the difficult views to learn, anyhow let's learn how to add a tableview in our view.
A tableView is used to show a list of objects.

Adding a TableView Using Interface Builder

1. Prepare the superview of your tableView. (Superview is the view where we would like to put our tableview.) In our example, the UIViewController's view is going to be our tableView's superview.

2. Drag a tableView UI to our View.
If you hit run, you will see your tableView on your screen. You can scroll it up and down.

3. Set the tableview datasource and delegate in your Interface file.

@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>


4. Add an IBOutlet tableview property and synthesize it.

@property (nonatomic, strong) IBOutlet UITableView *sampleTableView
@synthesize sampleTableView; //.m file below @implementation ViewController

5. Connect your IBOutlet to our tableView in your xib file.



6. Create an array that will hold your list for you. If your items are static (will not change), use NSArray, else, if somewhere in your program, you need to change your array, use NSMutableArray.

@property (nonatomicstrong) NSArray *items;

7. In your viewDidLoad function, allocate and initialize your array with your objects. Currently, let's use simple string objects, NSString.
items = [[NSArray alloc] initWithObjects:@"Item No. 1"@"Item No. 2"@"Item No. 3"@"Item No. 4"@"Item No. 5"@"Item No. 6", nil];

8. Set our sampleTableView's datasource and delegate to its File's Owner.



9. Lastly, implement the UITableView Datasource and Delegate methods. These are necessary to manipulate our tableView.


#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    // Return the number of rows in the section.
    // Usually the number of items in your array (the one that holds your list)
    return [items count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    //Where we configure the cell in each row

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell;
    
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    // Configure the cell... setting the text of our cell's label
    cell.textLabel.text = [items objectAtIndex:indexPath.row];
    return cell;
}

/*
 // Override to support conditional editing of the table view.
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
 // Return NO if you do not want the specified item to be editable.
 return YES;
 }
 */

/*
 // Override to support editing the table view.
 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
 if (editingStyle == UITableViewCellEditingStyleDelete) {
 // Delete the row from the data source
 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
 }
 else if (editingStyle == UITableViewCellEditingStyleInsert) {
 // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
 }
 }
 */

/*
 // Override to support rearranging the table view.
 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
 {
 }
 */

/*
 // Override to support conditional rearranging of the table view.
 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
 {
 // Return NO if you do not want the item to be re-orderable.
 return YES;
 }
 */

#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
    // If you want to push another view upon tapping one of the cells on your table.

    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     */
}


10. Hit Run!


Adding a TableView Programmatically

1. From the steps we had above, delete the tableView UI in our xib file, and delete the IBOutlet from our tableView property.

@property (nonatomicstrongIBOutlet UITableView *sampleTableView

2. On your viewDidLoad function (of your ViewController.m file). Follow the commented steps.

- (void)viewDidLoad {
    [super viewDidLoad];
    //Create a tableView programmatically
    self.sampleTableView = [[UITableView alloc] initWithFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.yself.view.frame.size.widthself.view.frame.size.height 2) style:UITableViewStylePlain];
    //Add the tableview as sa subview of our view ---> making "view" our superview.
    [self.view addSubview:sampleTableView];
    //From step 7 above.
    items = [[NSArray allocinitWithObjects:@"Item No. 1"@"Item No. 2"@"Item No. 3"@"Item No. 4"@"Item No. 5"@"Item No. 6"nil];
    //From the step 8 above, this is how we do that programmatically
    self.sampleTableView.delegateself;
    self.sampleTableView.dataSourceself;
}

3. Done! When you hit run, you'll see the same result.




27 comments:

  1. great job. your blog is very useful.

    thanku

    ReplyDelete
    Replies
    1. You're welcome. I hope you learned and found it really easy and simple.

      Delete
    2. Hi Jenn, I love your tutorials. May I ask a question?

      Greetings from Switzerland, Ronald

      Delete
  2. how to add a "add" button and "delete" button in nav bar to insert / delete rows dynamically ?

    ReplyDelete
    Replies
    1. I'll make a simple tutorial about adding/deleting rows dynamically.

      Delete
    2. http://iosmadesimple.blogspot.com/2013/04/addingdeleting-rows-dynamically.html

      Delete
  3. I'm getting an error in this line - [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

    @[indexPath] ??

    I have the array declared as textArray1 = [[NSArray alloc]initWithObjects:@"one",@"two",@"Something", nil];

    ReplyDelete
    Replies
    1. instead of @[indexPath]... change it with

      [NSIndexPath indexPathForRow:0 inSection:0]; <-- deletes the first row in section 0 (just change the Row and Section)

      Delete
  4. I am Struck in UITableview , Can you tell me how many times cellForRowAtIndex is called, and upon scrolling it is called, due to which the text on each cell is override.

    How to get rid of this problem.

    ReplyDelete
    Replies
    1. try to put a breakpoint to your cellForRow method to know how many times it's being called. It is called every time you scroll. And because of the tableview using reusable cells that's why text on each cell is overridden. though, I do not really know how your code looks like in cellForRow method.

      Delete
    2. Also, cellforrow is called every time there's a new cell to be shown

      Delete
  5. @Jenn I agree Every Time we scroll the tableview CellForRowAtIndex is called. but what is happening to my code, for the first time itself it is called twice due to which all labels and images are override.

    you know when I check it using break point. After the return statement,it should return back the cell rows to the method i.e. CellForRowAtIndex but unfortunately it came inside the CellForRowAtIndex, due to which the onject in tablecells are overridden.

    I need you advice how to remove this bug from my app.This is a huge blunder in my app and I want to resolve this ASAP.




    ReplyDelete
    Replies
    1. Hope you can refer to http://stackoverflow.com/ regarding your problem.. That might have something to do with your code. And I don't always have the luxury of time to answer your question and debug. Thanks

      Delete
  6. Couldn't finish, got no File Owner in Xcode.

    ReplyDelete
  7. Thank you. This was helpful. I hope all is well with you today. David

    ReplyDelete
  8. Hi Jenn. I am very new to iOS development. I have a problem how can I add multiple tableview to single view and in each table one image. If I rotate simulator I should get image || image|| image|| like that format. I tried so many times but failed. can you please help me
    my email madira.1587@gmail.com

    ReplyDelete
  9. Thanks for sharing such a awesome article
    http://quincetravels.com

    ReplyDelete

Blocks From one Class to Another

One popular scenario in using blocks is when you need to update your view after a web service call is finished.