I am new to iOS. I have a table view where i want to load different custom cells.
Here is my code from tableViewCellForRowAtIndexPath:
if (self.mainTableView .tag==SEARCH)
{
static NSString *cellId=#"Cella";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil)
{
NSArray *topLevelOjects= [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell=[topLevelOjects objectAtIndex:0];
}
//code goes here
return cell;
}
else
{
static NSString *mCell = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:mCell];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
}
//code goes here
return cell;
}
In method numberOfRowsInSections:(UITableView *) tableview I have:
if (tableView.tag==SEARCH)
{
return [firstList count];
}
else
{
return [secondList count];
}
The problem i have is that every time ELSE is executed the tableview contains both the first and second CustomCell. WHY?
I finally found the issue. The identifier used on else branch was actually the identifier used for the CustomCell *cell =.. (if branch). There was no Cella identifier:).
Related
I would like to change the format of the first cell in my UITableView (masterViewController), so that the image stretches across thewidth of the whole cell and the text label is shown above the image. Also would like to add a second text label to this cell only?
Any help on how to do this would be great, I have looked without success for this particular problem and I am fairly new to UITableViews.
Make one custom cell as per your requirement and load it for indexpath.row== 0 and simple UITableViewCell for all other cells. hope it will helps you
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomCell *customcell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
static NSString * identifier = #"Cell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(indexPath.row == k)
{
if(customcell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
scrlcell = [nib objectAtIndex:0];
}
}
else{
if(cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
}
if(indexPath.row == k)
return customcell;
else
return cell;
}
You should build a custom cell (you can build it in Interface builder) and then use it on your indexPath.row == 0. Like this:
static NSString *CellIdentifier = #"CellIdentifier";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell)
{
NSArray *topLevel = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for (id currentObject in topLevel){
if ([currentObject isKindOfClass:[CustomCell class]])
{
cell = currentObject;
break;
}
}
}
if(indexPath.row == 0){
// Use your cell here
}else{
// Build a new cell
}
return cell;
This question already has answers here:
2 different types of custom UITableViewCells in UITableView
(3 answers)
Closed 9 years ago.
I'm having an issue and would like to know if what I am trying to do is even possible.
I have a ViewController that has a UITableView as a subview. I then loaded a custom cell and it worked fine. However, I needed another custom cell in the same tableview - this second cell has a separate nib as well.
Is this possible?
Two different custom cells in on section in a UITableView?
I did try something like this:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
// Space Cell
if (indexPath.row== 0) {
CellSpace *cell = (CellSpace *) [tableViewdequeueReusableCellWithIdentifier:CellIdentifier2];
return cell;
}
// Content cell
else {
CellView *cell = (CellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
// Configure cell
return cell;
}
}
However it seems the else statement is never fired and I normally get a crash saying the method returned nil.
UPDATE
I used the advice and code here and came up with this:
#pragma mark - UITableView Delegate Methods
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 160;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 22;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier1 = #"UsernameCell";
static NSString *CellIdentifier2 = #"PasswordCell";
if(indexPath.row == 0) {
BBUsernameRegistrationCell *cell = (BBUsernameRegistrationCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if(cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier1 owner:self options:nil]; // set properties
cell = nib[0];
}
// set properties
return cell;
}
// Content cell
else {
BBPasswordTableViewCell *cell = (BBPasswordTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if(cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier2 owner:self options:nil]; // set properties
cell = nib[0];
}
// set properties
return cell;
}
}
However I only see the first Cell in my tableview. If I switch the cells around the second one loads. But not both at the same time. Does anyone have any idea why?
Yes, it is possible..
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
// Space Cell
if (indexPath.row== 0) {
CellSpace *cell = (CellSpace *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if(cell == nil) {
cell = [[CellSpace alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1];
// set properties
}
// set properties
return cell;
}
// Content cell
else {
CellView *cell = (CellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if(cell == nil) {
cell = [[CellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
// set properties
}
// set properties
return cell;
}
}
in your custom cell, do something like this in initWithStyle method:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CellView" owner:self options:nil];
for (id currentObj in topLevelObjects ) {
if ([currentObj isKindOfClass:[CellView class]]) {
self = (CellView*) currentObj;
}
}
return self;
}
Yes it is possible. But before use this dequeueReusableCellWithIdentifier:. Just register your cell and corresponding nib files.
code as..
-(void)initiateCellRegisteration
{
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
[self.tableView registerClass:[ContentCell class] forCellReuseIdentifier:CellIdentifier2];
[self.tableView registerNib:[UINib nibWithNibName:CellIdentifier2 bundle:nil] forCellReuseIdentifier:CellIdentifier2];
[self.tableView registerClass:[SpaceCell class] forCellReuseIdentifier:CellIdentifier1];
[self.tableView registerNib:[UINib nibWithNibName:CellIdentifier1 bundle:nil] forCellReuseIdentifier:CellIdentifier1];
}
Call this method in viewDidLoad
If you are using the cell nib then you need little tricky way to get your cell nib like
static NSString *CellIdentifier = #"ProductCell";
IVProductCell *cell = (IVProductCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"IVProductCell" owner:nil options:nil];
for (id currentObject in objects) {
if ([currentObject isKindOfClass:[IVProductCell class]]){
cell = (IVProductCell*) currentObject;
}
}
}
I'm building an app where a screen should show a tableview where in the tableview first two row are two different custom cells and the rest are different custom cells. So I have did this in my cellForRowAtIndexPath:
My Code:
if (indexPath.row == 0 && !isSearchEnabled) {
FirstRowViewCell *cell;
static NSString *CellIdentifier = #"FirstCell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// load a new cell from the nib file
[[NSBundle mainBundle] loadNibNamed:#"ContactCell" owner:self options:nil];
cell = self.firstCell;
//cell.delegate = self;
//cell.indexPath = indexPath;
self.firstCell = nil;
}
return cell;
} else if (indexPath.row == 1 && !isSearchEnabled) {
SecondRowViewCell *cell;
static NSString *CellIdentifier = #"SecondCell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// load a new cell from the nib file
[[NSBundle mainBundle] loadNibNamed:#"ContactCell" owner:self options:nil];
cell = self.secondCell;
//cell.delegate = self;
//cell.indexPath = indexPath;
self.secondCell = nil;
}
return cell;
}else {
static NSString *CellIdentifier = #"ContactCell";
ContactTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"ContactCell" owner:self options:nil];
// load a new cell from the nib file
cell = self.contactCell;
cell.delegate = self;
cell.indexPath = indexPath;
self.contactCell = nil;
}
return cell;}
but its lagging when scrolling the tableview. When I checked with the Time Profiler in instruments its showing that cellForRowAtIndexPath especially the
[[NSBundle mainBundle] loadNibNamed:#"ContactCell" owner:self options:nil];
is taking much time to load which causes lag. My question is, do the cell getting reused or not, because the above line getting executed for each and every cell even we are scrolling to the top. Please help me to get through the lag problem. Thanks!
try this may be it will helps
static NSString *simpleTableIdentifier = #"ContactCell";
ContactCell *cell = (ContactCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ContactCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
return cell;
You are creating cells that do not have the reuseIdentifier set. reuseIdentifier is a readonly property of UITableViewCell. What you should do instead is register the nib with the tableview, perhaps in the viewDidLoad or viewWillAppear method of your UIViewController.
UINib *cellNib = [UINib nibWithNibName:#"ContactCell" bundle:nil];
[tableView registerNib:nib forCellReuseIdentifier:CellIdentifier];
Once you do this, dequeueReusableCellWithIdentifier: will always return a valid cell, whether it is instantiating it or reusing it for you.
You can refer to this Apple documentation: UITableView, UITableViewCell, and UINib.
UITableViewCell custom cell's contents such as UILabel text, UIButton title resets to default values(Label, Button) after Scrolling the Table View.I using number of custom cell in single table view. These is are code which i used to generate number of custom cell in single table view with different identifier and different custom cell name for each and every cell.
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = (customCell1 *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) cell = [[customCell1 alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
{
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"customCell1" owner:self options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (customCell1 *)currentObject;
break;
}
}
}
static NSString *CellIdentifier2 = #"cell2";
UITableViewCell *cell2 = (customCell2 *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell2 == nil) cell2 = [[customCell2 alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
{
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"customCell2" owner:self options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell2 = (customCell2 *)currentObject;
break;
}
}
}
cell.label = #"Test";
[cell2.button setTitle:#"Test Button" forState:UIControlStateNormal];
return cell;
return cell2;
As you are setting the cell/cell2 to a UITableViewCell loaded from NIB, the reuse identifier(s) will be whatever was set in the XIB.
Anyway, the code you pasted in has quite a few issues. Is that the one you are really using? cell2 will be never returned.
The cells in table view are dynamically created by dequeuing using the cell identifier.In the code you mentioned above will always return first "return cell";
The data source method can return only one cell at a time after the creation. So if you want to return a cell depending of your use you have to do like below
(UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Ideally a custom cell should be created like this
if(condition when you wan this cell1)
{
//create the custom cell1 here and return it as given below
static NSString *cellIdentifier = #"MyCustomCell";
// Similar to UITableViewCell
MyCustomCell *cell = (MyCustomCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
return cell1;
}
else if(when you want to create this cell2)
{
// create the custom cell2 here and return it
return cell2;
}
// Create the default UI table view cell and return it . if any of the above condition did not satisfied, it will return the default cell.
// create default UI table here and return it
return cell;
}
I've a custom UITableViewCell subclass and I've read that this is supposed to be the correct way of loading custom cells for iOS 5:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"customCell"];
// Configure cell
cell.nameLabel.text = self.customClass.name;
}
return cell;
}
But the label text is not shown when I run the app. However, I also tried this way:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (CustomCell *)view;
}
}
// Configure cell
((CustomCell *)cell).nameLabel.text = self.customClass.name;
}
return cell;
}
This way the label is displayed, but any reuseIdentifier is set in loadNibName: method. What the best way of loading custom cells should be? I need to support iOS 5+. Could the first approach not be working because I'd to configure cell's labels and styles in initWithStyle: method and not in the table view's method?
Thanks!
The error in your code is that cell.nameLabel.text is only set in the if (cell == nil) { ... } case and not generally.
The easiest ways to load custom cells are
Use registerNib:forCellReuseIdentifier: if the cell is defined in a nib file, or
use registerClass:forCellReuseIdentifier: if the cell is created programmatically, or
use a Storyboard and define "CustomCell" as "Prototype Cell" for the table view.
For example (in viewDidLoad):
[self.tableView registerNib:[UINib nibWithNibName:#"CustomCell" bundle:nil] forCellReuseIdentifier:#"customCell"];
Then dequeueReusableCellWithIdentifier
will always return a cell, so that cellForRowAtIndexPath simplifies to
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
cell.nameLabel.text = self.customClass.name;
return cell;
}
Just use this code and try.
static NSString *cellIdentifier=#"cell";
YourCustomCell *cell = (YourCustomCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSString *customeCellName = [NSString stringWithFormat:#"%#",[YourCustomCell class]];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:customeCellName owner:self options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (YourCustomCell *) currentObject;
break;
}
}
}
cell.nameLabel.text = self.customClass.name; // Make sure self.customclass.name have value.
return cell;
Use this code (NewCustomCell is your Custom UITableViewCell class name)...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NewCustomCell *cell = (NewCustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib=[[NSBundle mainBundle]loadNibNamed:#"NewCustomCell" owner:self options:nil];
cell=[nib objectAtIndex:0];
}
return cell;
}
Happy coding... :)