9

I am creating the cell programatically using the reuse identifier.

Note - I am not using storyboard for creating the cell

Whenever the cell is dequeued, the cell is nil, so the cell needs to be newly created using alloc, which is expensive.

EDIT (added 1 more question and corrected code)

Question

  • Why does this dequeue always return nil ? How can I correct it ?
  • Does dequeue work only when used along with storyboard / nib file ?

Code

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if(!cell) //Every time cell is nil, dequeue not working 
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    }

    return cell;
}
user1046037
  • 16,755
  • 12
  • 92
  • 138
  • 2
    How often exactly does it return nil? And how many of those cells are displayed simultanously on your devices screen? Reusing means to re-use those cells only, that were just scrolled off the screen. – Hermann Klecker Nov 14 '12 at 13:24
  • And Srikar is right. The appropriate cell identifier must be set on the newly created cells. – Hermann Klecker Nov 14 '12 at 13:30
  • It returns nil always. 4 cells are displayed at a given time and when I scroll dequeue returns nil. – user1046037 Nov 14 '12 at 14:52

4 Answers4

12

You need to first set the CellIdentifier as Cell. Are you doing that? When you are creating a new cell you need to assign this identifier Cell to it. only then iOS will be able to dequeueReusableCellWithIdentifier with that identifier. Programatically you can do it like so -

UITableViewCell *cell = [[UItableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"Cell"];

You can set identifier from Interface Builder too -

enter image description here

Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
  • 1
    I am not using storyboard, I am creating the cell programatically. So I don't think this solution might be applicable. correct me if i am wrong – user1046037 Nov 14 '12 at 14:56
  • hey man i provided the solution for both. Please read the answer properly. first i gave programatic solution then for the sake of completeness provided the IB solution too. – Srikar Appalaraju Nov 14 '12 at 15:02
  • sorry about that, NSString CellIdentifier is set as @"Cell". Note the original code has been updated now. I am doing that, it is present in the code that i have pasted. Can you let me know if i am missing something. Still not working. – user1046037 Nov 14 '12 at 15:11
11

I was making a couple of mistakes:

  1. I was using a subclass of UITableViewController, but was creating the tableView outside of the subclass
  2. There is a tableView created in the table view controller, which is self.tableView In the tableview controller while returning the cell for index path, I was using self.tableView instead of tableView.
  3. Also, ensure that the cell identifier is declared as static

    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    

Since tableView and self.tableView were representing different tables, the cell was not being dequeued from the same table and hence was always nil

Jojodmo
  • 23,357
  • 13
  • 65
  • 107
user1046037
  • 16,755
  • 12
  • 92
  • 138
2

This code should be generating the warning "control reaches end of non-void function" because you aren't actually returning anything. Add return cell; to the end of the function. Additionally, you never add the reuse identifier to the newly created cells.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";    
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    return cell;
}
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
  • while pasting the code i had missed out a few lines, now i have edited and updated. The code that you pasted is what I am using. Yet it returns nil every time. – user1046037 Nov 14 '12 at 14:57
1

First declare cell identifier for a tableViewCell at the viewDidLoad method as:

[tableView registerClass:UITableViewCell.class forCellReuseIdentifier:@"MyCell"];

Now recall the instance of the UITableViewCell with the same identifier "MyCell" as:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell" forIndexPath:indexPath];

Further just fill up the cell .. Now logic executes that limited number of cells are able to show enormously large list efficiently (using dequeue concept).

But remember to assign value (even nil if required) to every UIView used in the cell, otherwise overwriting / overlapping of text / images will happen.

Shanu ji
  • 359
  • 4
  • 5