Subtitle in dequeueReusableCellWithIdentifier - ios

I have this code
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
Song *song = [self.music objectAtIndex:indexPath.row];
cell.textLabel.text = song.title;
cell.detailTextLabel.text = song.artist;
return cell;
I don't use Interface Builder. How I can make this cell to have a subtitle? All I get is a standard cell.

There are two approaches:
The old style approach is to not register any class, NIB or cell prototype, call dequeueReusableCellWithIdentifier without forIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
Song *song = self.music[indexPath.row];
cell.textLabel.text = song.title;
cell.detailTextLabel.text = song.artist;
return cell;
}
As we discussed elsewhere, this assumes that you do not register a class for that reuse identifier.
The alternative is to register your own class in viewDidLoad:
[self.tableView registerClass:[MyCell class] forCellReuseIdentifier:#"Cell"];
and then call dequeueReusableCellWithIdentifier with forIndexPath option, but lose the code that manually tests if it is nil (because it never will be nil):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
Song *song = self.music[indexPath.row];
cell.textLabel.text = song.title;
cell.detailTextLabel.text = song.artist;
NSLog(#"title=%#; artist=%#", song.title, song.artist); // for diagnostic reasons, make sure both are not nil
return cell;
}
This obviously assumes that you've implemented a UITableViewCell subclass that includes the subtitle (note I'm overriding the style):
#interface MyCell : UITableViewCell
#end
#implementation MyCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
}
#end
Personally, I think designing a cell prototype (which automatically registers the reuse identifier and takes care of all of this other stuff) is much easier. Even the old technique of registering a NIB is easier than the above. But if you want to do it entirely programmatically, those are the two approaches.

Try this in your cellForRowAtIndexPath method
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
Hope it helps.

Try this code :
UITableViewCell *cell= [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell==nil) {
// Using this way you can set the subtitle
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
Song *song = [self.music objectAtIndex:indexPath.row];
cell.textLabel.text = song.title;
cell.detailTextLabel.text = song.artist;
return cell;

Related

Is there a way to ignore to register a nib or a class for TableViewCell?

My table simply has row with a UIImageView. When I assign the image directly like the below mentioned way
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"cellidentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
// Configure the cell...
cell.imageView.image = [self.backgroundImages objectAtIndex:indexPath.row];
return cell;
}
It returns error:
unable to dequeue a cell with identifier cellidentifier - must
register a nib or a class for the identifier or connect a prototype
cell in a storyboard'.
So I wonder is there a way to ignore to register a nib or a class for UITableViewCell in order to shorten the code in this case?
If you are using custom class for your cell then you should register the class (in viewDidLoad),use registerNib:forCellWithReuseIdentifier: if the cell is made in a xib file.
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
else write cellForRowAtIndexPath tableView delegate as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//Configure cell
return cell;
}
You just need to add one line in your viewDidLoad to resolve the error
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cellidentifier"];
}
Put your cell identifier in storyboard as below screenshot.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Songcell"; // copy this identifier and paste it into your storyboard tableviewcell indetifier
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UIImageView *IMAGEVIEWNAME = (UIImageView*)[cell viewWithTag:YOUR_TAG]; // give tag to your imageview from storyboard and access it here
IMAGEVIEWNAME.image = [UIImage imageNamed:#"YOURIMAGENAME"];
return cell;
}
Give same name in your storyboard tableviewcell identifier
cellidentifier with this name . i just give my cell identifier songcell.

UITableViewCell subtitle not appearing on load

I have a table with cells where the subtitle only appears after something has been searched. This is the code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if(tableView == self.tableView)
{
// Configure the cell...
cell.textLabel.text = self.objects[indexPath.row];
cell.detailTextLabel.text = #"test2";
}
else{
// Configure the cell...
cell.textLabel.text = self.results[indexPath.row];
cell.detailTextLabel.text = #"test1";
}
return cell;
}
EDIT: ArtOfWarfare's answer was correct. it was a problem in the storyboard. See image below:
Your code suggests that you have two separate tables... I would suggest that your problem lies within the differences in how the tables have been configured, possibly in your Storyboard.
Do you, perchance, have one of them set with a prototype with an identifier of "Cell" but a style that isn't UITableViewCellStyleSubtitle? That would make it so that your cell creation method isn't called in one, but only in the other.

Tableview subtitles on IOS7

I'm trying to add a subtitle to my tableview cells, but they are not displayed.
Where is the mistake?
Is the row
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle]
up-to-date, also with iOS 7?
Best regards
Frank
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"TestA";
cell.detailTextLabel.text = #"TestB";
return cell;
}
This code:
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
will never execute because dequeueReusableCellWithIdentifier: forIndexPath: is guaranteed to allocate a new cell.
Unfortunately, registerClass:forCellReuseIdentifier: doesn't let you specify a UITableViewCellStyle.
Change dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath to simply dequeueReusableCellWithIdentifier:CellIdentifier. This method does not guarantee a cell will be returned.* When it's not, your code will then create a new cell with the style you want.
* - (It will if you're using a storyboard, as rdelmar points out, but that's not the case here.)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.textLabel.text = #"Title1";
cell.detailTextLabel.text = #"Subtitle 1";
return cell;
}
I had a similar problem and no solution on the internet worked for me. Turns out I was being an idiot. I'll post my solution just incase someone else experience a similar scenario.
I am assuming that you are using storyboard, have created a prototype and set the style to subtitle
In your storyboards document outline, make sure you select the protoptype cell and select the subtitle. See image:
Now ensure that the label font colour is of a nature that us visible on your background!
Simply subclass UITableViewCell and override
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;
with the first line being
[super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
And register your cell class with the table view
[tableView registerClass:[YourCellSubclass class] forCellReuseIdentifier:#"YourCellID"];

Nib prototype uitableviewcell cellForRowAtIndexPath:

Trying to set and access nib tableview cell. Basically the same as creating uitableview with a prototype tableviewcell and setting its identifier and accessing it through
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Fill table in with data
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
Question is how would you do this as a nib. As nib IB doesn't have prototype option?
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
MPMediaItem *song = [self.songsList objectAtIndex:indexPath.row];
NSString *songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
NSString *durationLabel = [song valueForProperty: MPMediaItemPropertyGenre];
cell.textLabel.text = songTitle;
cell.detailTextLabel.text = durationLabel;
return cell;
}
-(void)viewDidLoad {
[self.tableView registerNib:[UINib nibWithNibName:#"MusicViewController" bundle:nil] forCellReuseIdentifier:#"Cell"];
}
Create a custom tableviewCell with the nib file.After creation you have three files YourCustomCell.h YourCustomCell.m and YourCustomCell.xib
Add the IBOutlet in YourCustomCell.h and connect them in YourCustomCell.xib with respective labels.
Now in cellForRowAtIndexPath: add the following:
YourCustomCell *yourCustomCell = [self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
yourCustomCell.labelInCustomCell.textLabel.text = songTitle;
yourCustomCell.detailsLabelInCustomCell.textLabel.text = durationLabel;
return yourCustomCell;
Hope this help you.
You make your cell in the xib file and then in code (probably in viewDidLoad) register the nib with registerNib:forCellReuseIdentifier:. In cellForRowAtIndexPath, you just dequeue a cell with the same identifier that you passed to the register method. No need to put in the if (cell == nil) clause, because it will never be nil.

cellForRowAtIndexPath: Is it XCode template correct?

This question is about cellForRowAtIndexPath.
As I know the correct way is
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"Cell"];
return cell;
But when I created Master-Detail template, code looks like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[object valueForKey:#"timeStamp"] description];
}
EDIT: The question is not about configureCell atIndexPath. As you see these strings absent in XCode template.
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] ;
Is XCode template correct?
The template code is correct.
Beginning with iOS 5.0 it's possible to register a nib for a cell identifier. Whenever the table needs a cell and there are no reusable cells left it instantiates the nib and creates the cell by itself.
If you do so dequeueReusableCellWithIdentifier: always returns a cell; you don't have to create it yourself.
The API to register nibs is: registerNib:forCellReuseIdentifier:.

Resources