Optimize CellForRow Method for multiple cells - ios

Can anyone help me with how to optimize following code if we do have same contents inside both the cells such like 2 labels and 1 imageview than.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == booksTbl) { // Your conditions here to choose between Books and Movies
BookCell *cell = [tableView dequeueReusableCellWithIdentifier:#"bookCell"];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"bookCell"];
}
return cell;
} else {
MovieCell *cell = [tableView dequeueReusableCellWithIdentifier:#"movieCell"];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"movieCell"];
}
return cell;
}
I have tried by taking UITablewViewCell As common and according to condition, i was casting it with the appropriate cell. But it doesn't work for me.

Try this one:
BookCell *cell = (BookCell*)[tableView dequeueReusableCellWithIdentifier:#"bookCell"];
if(cell == nil){
// NSLog(#"---Cell Allocated Memory---");
cell = (BookCell *)[[[NSBundle mainBundle] loadNibNamed:#"BookCell" owner:nil options:nil] lastObject];
[cell setRestorationIdentifier:#"bookCell"];
}

Related

UITableview with two different custom cells overlapping while scrolling

I have a UITableView with two different custom cells. One will show normal text message and other with some text and image. I am able to use two different custom cells in cellForRowAtIndexPath and able to see two different cells like below
But whenever i scroll the tableview then the cells are overlapping like below.
Below is my code
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
//minimum size of your cell, it should be single line of label if you are not clear min. then return UITableViewAutomaticDimension;
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
id cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[TicketTableViewCell class]]) {
return 171;
} else {
return UITableViewAutomaticDimension;
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [chatHistoryArr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *msgTypeStr = [msgTypeArr objectAtIndex:indexPath.row];
if ([msgTypeStr isEqualToString:#"msg"]) {
static NSString *simpleTableIdentifier = #"ChatConversationTableViewCell";
ChatConversationTableViewCell *cell = (ChatConversationTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ChatConversationTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.chatmsgLabel.text = [chatHistoryArr objectAtIndex:indexPath.row];
cell.timeAndDateMsgLabel.text = [timeAndDateMsgArr objectAtIndex:indexPath.row];
return cell;
}
else{
static NSString *simpleTableIdentifier = #"TicketTableViewCell";
TicketTableViewCell *cell = (TicketTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TicketTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.tktMsgTxtView.text = [chatHistoryArr objectAtIndex:indexPath.row];
cell.ticketDateAndTimeLbl.text =[timeAndDateMsgArr objectAtIndex:indexPath.row];
return cell;
}
}
No issues in showing data or showing different cells, only problem is overlapping. I have already tried the available solutions but no luck. Below is one of them.
adding the below code in cellForRowAtIndexPath but no use.
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
Tried a lot to fix the issue but no luck. Any help will be really appreciated.
Change your code of tableViewCell height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *msgTypeStr = [msgTypeArr objectAtIndex:indexPath.row];
if ([msgTypeStr isEqualToString:#"msg"]) {
return UITableViewAutomaticDimension;
} else {
return 171;
}
}
It will resolve your overlap issue.
Try this once
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell %d",indexPath.row];
UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
if (cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

Cell at indexpath 0 not displaying correctly

I have a UITableView with sections inside of them. All works great, but I can't seem to figure out how to customize the very fist index path. For example, I know this is very easily achievable through a normal tableview like so:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
if (indexPath.row == 0)
{
cell.detailTextLabel.text = #"My Custom text";
NSLog(#"%#",pm1.customText1);
}
}
}
I have tried the above implementation and it does not seem to work for me. Is there a different approach for section headers to achieve the same result with a normal tableview? Do I need to inject a "fake" section in my dictionary?
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (indexPath.row == 0) {
cell.detailTextLabel.text = #"My Custom text";
NSLog(#"%#",pm1.customText1);
}
return cell;
}
Try this
The way you have it now the first cell is customize only when cell is nil.
You should move it out of the if statement.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//check for first cell
if (indexPath.row == 0) {
cell.detailTextLabel.text = #"My first Cell";
NSLog(#"%#",pm1.customText1);
}else{
cell.detailTextLabel.text = #"Other cells";
NSLog(#"other cells");
}
return cell;
}

Why is my cell nil

I am writing the code to populate a UITableView from using a CoreData database wrapped in magical record. For some reason though the code docent seem to be working and my cell is considered nil. Why is this happening?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
PassWhizEntity *pazz = [allPasses objectAtIndex:indexPath.row];
cell.textLabel.text = pazz.destinationTeacherAttribute;
//cell.detailTextLabel.text = [self.dateFormatter stringFromDate:pazz.dateAttribute];
if (cell == nil)
{
NSLog(#"cell was nil");
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
it just prints cell was nil and loads a blank UITable. Any ideas?
Your code should be like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSLog(#"cell was nil");
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
PassWhizEntity *pazz = [allPasses objectAtIndex:indexPath.row];
cell.textLabel.text = pazz.destinationTeacherAttribute;
//cell.detailTextLabel.text = [self.dateFormatter stringFromDate:pazz.dateAttribute];
return cell;
}
You are trying to set textLabel of unallocated cell which have no effect on cell. Cell is returned nil because tableview don't have any cell that can be reused, so it is your responsibility to check for nil and make new Cell if needed.

How to use multiple reusable TableViewCells

I like to add multiple reusable UITableViewCells to a TableView. I am using this code to do this, but it won't work, it only shows the first cell.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
static NSString *costumeCell1 = #"Cell1";
AppDetailCell1 *cell1 = [tableView dequeueReusableCellWithIdentifier:costumeCell1];
if (!cell1) {
cell1 = [[AppDetailCell1 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:costumeCell1];
}
return cell1;
}
if (indexPath.row == 1) {
static NSString *costumeCell2 = #"Cell2";
AppDetailCell2 *cell2 = [tableView dequeueReusableCellWithIdentifier:costumeCell2];
if (!cell2) {
cell2 = [[AppDetailCell2 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:costumeCell2];
}
return cell2;
} else {
return nil;
}
}
If you set the reuse identifiers properly, you should change this code part
AppDetailCell1 *cell1 = [tableView dequeueReusableCellWithIdentifier:costumeCell1];
if (!cell1) {
cell1 = [[AppDetailCell1 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:costumeCell1];
}
with this
AppDetailCell1 *cell1 = [tableView dequeueReusableCellWithIdentifier:costumeCell1 forIndexPath:indexPath];
There is no need if(!cell1), because dequeueReusableCellWithIdentifier: forIndexPath: method never returns nil, as I said before that properly reuse identifier set is important.

Custom cells issue in iOS 5

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... :)

Resources