Is there a way to use multiple uitableviewcell classes with nib files in the tableViewController?
There's this great tutorial video for how to create custom cell classes to be used in a tableViewController at the cellForRowAtIndexPath function that I'm pasting here in case anyone wants to see.
In this example though, they are only using one type of reusable cell class. This is from my own project but it's essentially what the tutorial presents. "videoCellEntry" is a custom cell that I have created with nib file videoEntryCell.xib, "videoEntry" is the class for each cell that I am configuring, and "videos" is an array of videoEntry.
I'm assuming to use multiple nib files, I can put some conditions to choose which nib file I want and then call a different loadNibNamed: portion like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"videoCellId";
videoEntryCell *cell =
(videoEntryCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
if(<condition 1>) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell" owner:self options:nil];
}
if(<condition 2>) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell2" owner:self options:nil];
}
cell = (videoEntryCell *)[nib objectAtIndex:0];
}
// Configure the cell.
videoEntry *vid = [videos objectAtIndex:indexPath.row];
[cell configureForVideoEntry:vid];
return cell;
}
But can the tableViewController handle multiple cell nib files? Or is there a better way? And wouldn't each cell require a different CellIdentifier depending on its nib file?
Yes, you can use multiple Nib-Files and multiple CellIdentifiers in the TableViewController. Just put your condition before the CellIdentifier. That's the way I've done it.
Some example inside the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method:
First define the variable cell:
UITableViewCell *cell;
Now the if-Block:
if(<condition 1>) {
static NSString *CellIdentifier = #"VideoCell1";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (UITableViewCell *) currentObject;
break;
}
}
}
// customize your cell here
}
if(<condition 2>) {
static NSString *CellIdentifier = #"VideoCell2";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell2" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (UITableViewCell *) currentObject;
break;
}
}
}
// customize your cell here
}
and finally:
return cell;
You can repeat the if-Block as often as you want. It's only important that you return a cell, which is not nil.
Related
I am getting an error when I try to show custom cell on my tableView. I have a nibFile connected with cells but I always get thread sigbart here
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CellForOffers" owner:self options:nil];
I don't know why, and my cell for row at index implementation is
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellForOffers";
CellForOffers *cell =(CellForOffers *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CellForOffers" owner:self options:nil];
cell = [nib objectAtIndex:0];
appDC * application = [dataArray objectAtIndex:[indexPath row]];
cell.namelbl.text=application.o_name;
cell.descriptionlbl.text=application.o_description;
[cell.imageView setImageWithURL:[NSURL URLWithString:application.o_image_url]];
}
return cell;
}
Add nib with its class like bellow...
cell = (CellForOffers *)[nib objectAtIndex:0];
I've been searching a lot but didn't find anything useful related to multiple custom rows, I need to create a settings tableView for my app,in which I need to load the rows from xib files,like:
ROW 1 =>> XIB 1.
ROW 2 =>> XIB 2.
ROW 3 =>> XIB 3.
ROW 4 =>> XIB 4.
My present code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell=nil;
//We use CellType1 xib for certain rows
if(indexPath.row==0){
static NSString *CellIdentifier = #"ACell";
cell =(ACell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"ACell" owner:self options:nil];
cell = (ACell *)[nib objectAtIndex:0];
}
//Custom cell with whatever
//[cell.customLabelA setText:#"myText"]
}
//We use CellType2 xib for other rows
else{
static NSString *CellIdentifier = #"BCell";
cell =(BCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"BCell" owner:self options:nil];
cell = (BCell *)[nib objectAtIndex:0];
}
//Custom cell with whatever
//[cell.customLabelB setText:#"myText"]
}
return cell;
}
First you create some custom UITableViewCell classes (.h and .m), as many as you have xib files:
So you could have CellType1 and CellType2 for example.
CellType1.h would look something like
#import <UIKit/UIKit.h>
#interface CellType1 : UITableViewCell
#property(nonatomic,strong) IBOutlet UILabel *customLabel;
#end
Then you create the xib files, you can use default view type, but then, just remove the view that is automatically created, replace that by a UITableViewCell, and change the class to CellType1. Do the same for CellType2.
Then in your tableViewController, write cellForRow like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell=nil;
//We use CellType1 xib for certain rows
if(indexPath.row==<whatever you want>){
static NSString *CellIdentifier = #"CellType1";
cell =(CellType1*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"CellType1" owner:self options:nil];
cell = (CellType1 *)[nib objectAtIndex:0];
}
//Custom cell with whatever
[cell.customLabel setText:#"myText"]
}
//We use CellType2 xib for other rows
else{
static NSString *CellIdentifier = #"CellType2";
cell =(CellType2*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"CellType2" owner:self options:nil];
cell = (CellType2 *)[nib objectAtIndex:0];
}
//Custom cell with whatever
[cell.customLabel setText:#"myText"]
}
return cell;
}
If you're not already familiar with loading a custom cell from a xib, check out the documentation here. To extend this to multiple custom xibs, you can create each table cell in a separate xib, give it a unique cell identifier, set the table view controller as the file's owner, and connect each cell to the custom cell outlet you define (in the docs, they use tvCell as this outlet). Then in your -tableView:cellForRowAtIndexPath: method, you can load the correct xib (or dequeue the correct reuseable cell) by checking which row you're providing a cell for. For example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier1 = #"MyIdentifier1";
static NSString *MyIdentifier2 = #"MyIdentifier2";
static NSString *MyIdentifier3 = #"MyIdentifier3";
static NSString *MyIdentifier4 = #"MyIdentifier4";
NSUInteger row = indexPath.row
UITableViewCell *cell = nil;
if (row == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer1];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell1" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
else if (row == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer2];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell2" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
else if (row == 2) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer3];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell3" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
else if (row == 4) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer4];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell4" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
// etc.
// Do any other custom set up for your cell
return cell;
}
I'm looking for solution...
Code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"ItemCardapio";
NSString *nibName = #"ItemCardapioCell";
ItemCardapioCell *cell = (ItemCardapioCell *) [self.restaurantsList dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
cell = (ItemCardapioCell *)[nib objectAtIndex:0];
[cell initCellWithRestaurant:#"" tipoRestaurante:#""];
}
return cell;
}
I find that with problems with cell repeating, the problem tends to occur when you put stuff you shouldn't in the if (cell == nil) bit.
The reason being is that the table view will end up using an incorrect re-used cell if you don't update certain aspects of your cell appropriately.
Try taking anything which directly changes your cell out of that if (cell == nil) bit, and it should stop problems with repeating cells.
Heres what I use for Custom cells:
static NSString *cellIdentifier = #"ItemCardapioCell";
ItemCardapioCell *cell = (ItemCardapioCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSLog(#"Creating Cell");
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ItemCardapioCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[ItemCardapioCell class]])
{
cell = (ItemCardapioCell *)currentObject;
break;
}
}
};
I am trying to display a custom TableView on a UIViewController but am getting an error "UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:"
I had connected the TableView to datasource and delegate.
Any suggestion to go about implementing so or do I need a UITableViewController?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCell"
owner:nil options:nil];
for (id currentObjects in topLevelObjects){
if ([currentObjects isKindOfClass:[UITableView class]]){
cell = (CustomCell *) currentObjects;
break;
}
}
}
//---set the text to display for the cell---
cell.cellNameLabel.text = #"This is name";
cell.cellValueLabel.text = #"This is Value";
return cell;
ERROR:
//NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCell"
owner:nil options:nil];
//in above owner should be self
// if ([currentObjects isKindOfClass:[UITableView class]]){
change this line to
if ([currentObjects isKindOfClass:[CustomCell class]]){
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"CustomCell"
owner:self options:nil];//owner should be self
for (id currentObjects in topLevelObjects){
if ([currentObjects isKindOfClass:[CustomCell class]]){
cell = (CustomCell *) currentObjects;
break;
}
}
}
//---set the text to display for the cell---
cell.cellNameLabel.text = #"This is name";
cell.cellValueLabel.text = #"This is Value";
return cell;
}
I try to make a custom cell with a Uilabel and textfield
And i get this:
-> http://data.imagup.com/9/1119535256.png
But it's not given given my value ("Titre" & "Valeur" are generic):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"InscriptionCustomCell";
InscriptionCustomCell *cell = (InscriptionCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"InscriptionCustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (InscriptionCustomCell *) currentObject;
break;
}
}
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if(indexPath.section ==0)
{
[cell.titreCell setText:[model.listModuleInfoPerso objectAtIndex:indexPath.row]];
[cell.contenuCell setPlaceholder:[model.listModuleInfoPerso objectAtIndex:indexPath.row]];
}else {
[cell.titreCell setText:[model.listModuleInfoSupp objectAtIndex:indexPath.row]];
[cell.contenuCell setPlaceholder:[model.listModuleInfoSupp objectAtIndex:indexPath.row]];
}
return cell;
}
No error :S, an idea?
Put an NSLog in the [model.listModuleInfoPerso objectAtIndex:indexPath.row] so you can see what is coming out...
You probably forgot to hook up the label and the text field from Interface Builder to the properties in your InscriptionCustomCell subclass.
Here it seems that you haven't set the delegate for UITextField. So, please set delegate now and then you can access the TextField entry.