Question

I am NOT using Storyboards. I have a UITableViewController and I would like to display a list of songs from user's library.

This is my code so far:

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
    NSArray *songs = [songsQuery items];

    return [songs count];
}

But for this block, I do not know what to do. I found a tutorial for storyboards, but it is not valid here:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
        static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
    NSArray *songs = [songsQuery items];

    MPMediaItem *rowItem = [songs objectAtIndex:indexPath.row];

    cell.textLabel.text = [rowItem valueForProperty:MPMediaItemPropertyTitle];
    cell.detailTextLabel.text = [rowItem valueForProperty:MPMediaItemPropertyArtist];

    return cell;
}

This only works in Storyboard because I can click the cell in the storyboard and rename its identifier to 'Cell'. In the .xib/nib file in my project, all I see is a view filled with country's names. I cannot click a single cell, I can only edit the whole table.

My question is, what code must I put in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath in order to display this list?

Thanks!

Was it helpful?

Solution

The basic problem you're encountering is that, when used in conjunction with a properly configured storyboard, dequeueReusableCell... will create a cell of the appropriate type if none is available to dequeue.

If you are using a standard UITableViewCell, you can use the following block to dequeue and/or create an appropriate cell:

static NSString*    reuseIdentifier = @"Cell";
UITableViewCell*    cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if(!cell)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
}

If, on the other hand, you're loading your cells from a nib file, you can just add:

[self.tableView registerNib:[UINib nibWithNibName:nibName bundle:[NSBundle mainBundle]] reuseIdentifier:reuseIdentifier];

to your viewDidLoad.

Alternatively you can use registerClass:forCellReuseIdentifier: if you have a custom cell class that sets up it's own subviews.

OTHER TIPS

First off, check if the cell being dequeued is nil or not.

The next thing I can see a problem with is the fact that you aren't really loading anything in cellForRowAtIndexPath:. Basically what this method does is dequeue some cell which has been marked for reuse in an attempt to save memory, and if you haven't set the proper Restoration Identifier in the Interface Builder, then there is no way to know which Nib you want initialized to use here.

What used to happen (or at least my understanding of it) is that in cellForRowAtIndexPath: you would have to check if the cell returned from dequeueReusableCellWithIdentifier: was nil, and if so, you'd have to create the cell from scratch using something like this:

SomeCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (!cell)
{
    cell = [[[NSBundle mainBundle] loadNibNamed:@"SomeCellNib" owner:self options:nil] objectAtIndex:0];
}

and this would ensure that if no cell was dequeued that you would load up a fresh one from scratch, although I believe that Apple actually changed how dequeueReusableCellWithIdentifier: works, and as long as you've registered the Identifier, it will create a new cell for you.

For this reason I'm not sure what the problem is if you've set the Identifier properly, and all I can suggest is to try and manually load the cell.

EDIT: I forgot to mention where Restoration Identifiers can be set. The Restoration Identifer field is in the Identity tab, or the third tab in the Interface Builder:

Location of Restoration Identifier in Interface Builder

To create a prototype cell inside a .nib, drag a UITableCellView out from the right sidebar. From there you can create your cell prototype, as well as set the cell reuse identifier.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top