Here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifierNormal = #"CellNormal";
static NSString *CellIdentifierTracking = #"CellTracking";
switch (self.mapState) {
case MapStateNormal:
{
// UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierNormal];
// if (cell == nil) {
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierNormal];
// }
[cell.textLabel setText:#"abc"];
return cell;
}
case MapStateTracking:
{
// UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierTracking];
// if (cell == nil) {
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierTracking];
// }
if (indexPath.row == 0) {
[cell.textLabel setText:#"Lorem ipsum"];
} else {
NSURL *url = [LoremIpsum URLForPlaceholderImageFromService:LoremIpsumPlaceholderImageServicePlaceKittenCom
withWidth:1024
height:1024];
[cell.imageView setImageWithURL:url
placeholderImage:[UIImage imageNamed:#"MenuButton"]];
}
return cell;
}
default:
break;
}
return nil;
}
This piece of code works fine but not the best practice because I re-create UITableViewCell everytime. It display like this:
However, when I uncomment those lines above to enable dequeueReusableCell then the table shows its cells with errors like this (the yellow part is my code):
You can see that there's an UIImage in first row and text in some rows below while I clearly didn't set it in my code.
What could I do to fix this ? or should I stick with the first method ?
Thanks.
You should really re-use the table view cells, because it is a lot of overhead if you recreate them all the time, i.e. the out-commented code is right.
Next, the docs say: "The table view's delegate in tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell."
If you do not reset the content, it will be shown again.
So I suggest that you set
cell.imageView.image = nil;
in your -(UITableViewCell *)tableView:cellForRowAtIndexPath:(NSIndexPath *)indexPath method.
Simply set [cell.textLabel setText:#""]; for each cell you dont't want to display any text. Cells are reused with the previous text, so you need to clear it.
Try this, clear the cell if it cell != nil
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifierNormal = #"CellNormal";
static NSString *CellIdentifierTracking = #"CellTracking";
switch (self.mapState) {
case MapStateNormal:
{
UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierNormal];
if (cell == nil) {
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierNormal];
} else {
[cell.textLabel setText:#""];
[cell.imageView setImage:nil];
}
...
return cell;
}
case MapStateTracking:
{
UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierTracking];
if (cell == nil) {
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierTracking];
} else {
[cell.textLabel setText:#""];
[cell.imageView setImage:nil];
}
....
return cell;
}
default:
break;
}
return nil;
}
Related
I have two tableview controllers lets say PopoverElementsListTable ,ElementsViewTable. one tableview will be in popover state when I click on one of the PopoverElementsListTable cell a custom cell has to added to the ElementsViewTable.I'm able to append only one cell when I try to add another cell to ElementsViewTable its getting replaced with previous cell.
#pragma mark - TableView delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section{
if (tableView == PopoverElementsListTable) {
return [myArray count];
}
else if (tableView == ElementsViewTable) {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath{
if (tableView == PopoverElementsListTable) {
static NSString *cellId = #"autoaddress";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:
UITableViewCellStyleDefault reuseIdentifier:cellId];
}
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
return cell;
}else {
NSLog(#"_selectedIndex %lu",(unsigned long)_selectedIndex);
if(_selectedIndex == 1){
AutoFillAddressFormElementcell * cell = [tableView dequeueReusableCellWithIdentifier:#"autoAddressCell"];
if (!cell) {
cell = [[AutoFillAddressFormElementcell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"autoAddressCell"];
}
return cell;
}else if(_selectedIndex == 2){
NSLog(#"Test # 123");
AddressSetterFormElementCell * cell = [tableView dequeueReusableCellWithIdentifier:#"setAddressCell"];
if (!cell) {
cell = [[AddressSetterFormElementCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"setAddressCell"];
}
return cell;
}else{
static NSString *cellId = #"autoaddress";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:
UITableViewCellStyleDefault reuseIdentifier:cellId];
}
cell.textLabel.text = #"List";
return cell;
}
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath{
if(tableView == PopoverElementsListTable){
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(#"Section:%ld Row:%ld selected and its data is %#",
(long)indexPath.section,(long)indexPath.row,cell.textLabel.text);
[_transarentView setHidden:true];
_selectedIndex = indexPath.row + 1;
NSLog(#"number %lu",(unsigned long)_selectedIndex);
[_displayFromElementTableView reloadData];
}
if(tableView == ElementsViewTable){
}
}
I know I'm able to append only one item because of return 1 in numberOfRowsInSection delegate. I tried replacing with another number but what I achieved is all the cells are identical.How can I get the dynamic count here? How to append customcells one by one which are unidentical.
You need to do it by identifying indexpath .
if (indexPath.row == 0) {
Customcell1 *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
}else if (indexPath.row == 1){
Customcell2 *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
}
return cell;
and so on....
You can check the table view too if you want.
My TableView has three different sections. Section 0 is for photo uploads its virtually empty until a user uploads a photo. However, my tableview is reusing cells from section 1 in section 2 and i'm not sure why. Here is the code below. Any help is greatly appreciated.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cell";
if (indexPath.section == 0) {
UploadsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UploadsCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.tag = indexPath.row;
cell.delegate = self;
cell.imageInfo = [_uploads objectAtIndex:indexPath.row];
[cell setCellInfo];
cell.backgroundColor = [UIColor redColor];
return cell;
}
else{
id object;
if (indexPath.section == 1) {
object = [self cacheObjectAtIndexPath:indexPath];
return [self tableView:tableView cellForRowAtIndexPath:indexPath withObject:object];
}
if (indexPath.section == 2) {
object = [self objectAtIndexPath:indexPath];
}
return [self tableView:tableView cellForRowAtIndexPath:indexPath withObject:object];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath withMobiObject:(MobiObject *)object{
static NSString *CellIdentifier = #"Cell";
StylesCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = (StylesCell*)[[StylesCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (object) {
[cell setObject:object];
}
return cell;
}
You should first begin by making your methods a bit more readable. Since you've asked me for it, I've rewritten one of your larger methods to use a switch when returning the correct configuration for cells based on their section.
As for your actual problem, it's very likely associated with the following lines returning the configuration for Section 1:
id object = [self cacheObjectAtIndexPath:indexPath];
return [self tableView:tableView cellForRowAtIndexPath:indexPath withObject:object];
As well as the other line returning configuration for Section 2:
id object = [self objectAtIndexPath:indexPath];
return [self tableView:tableView cellForRowAtIndexPath:indexPath withObject:object];
I'm not sure exactly what these methods return, so it's hard to say what exactly about them is returning duplicate cells.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section) {
case 0:
// Section is Zero
UploadsCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
cell.tag = indexPath.row;
cell.delegate = self;
cell.imageInfo = [_uploads objectAtIndex:indexPath.row];
[cell setCellInfo];
[cell setBackgroundColor:[UIColor redColor]];
return cell;
case 1:
// Section is One
id object = [self cacheObjectAtIndexPath:indexPath];
return [self tableView:tableView cellForRowAtIndexPath:indexPath withObject:object];
case 2:
// Section is Two
id object = [self objectAtIndexPath:indexPath];
return [self tableView:tableView cellForRowAtIndexPath:indexPath withObject:object];
default:
// Section is neither of the aforementioned sections.
break;
}
}
I have a tableView with a custom cell. I have the posibility to save to favorites some of the elements , and when this is happening i want to add a star image in cell. I was trying doing this , but after the star appears, i have a problem . I think it's because of reusable cell but i dont know how to solve it . My problem is : stars appear again on the other cells even if the word is not added on favorites.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
dictionaryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell=[[dictionaryTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.searchResult objectAtIndex:indexPath.row];
}
else
{
cell.word.text = self.tableData[indexPath.row];
BOOL isTheObjectThere = [self.favoriteArry containsObject:self.tableData[indexPath.row]];
if (isTheObjectThere==TRUE) {
cell.favImg.image=[UIImage imageNamed:#"3081#3x.png"];
}
}
return cell;
}
Replace following code in place of cellForRowAtIndexPath. you will get your desire output.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
dictionaryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell=[[dictionaryTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.favImg.hidden = YES;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.searchResult objectAtIndex:indexPath.row];
}
else
{
cell.word.text = self.tableData[indexPath.row];
BOOL isTheObjectThere = [self.favoriteArry containsObject:self.tableData[indexPath.row]];
if (isTheObjectThere==TRUE) {
cell.favImg.hidden = NO;
cell.favImg.image=[UIImage imageNamed:#"3081#3x.png"];
}
}
return cell;
}
Hope this help you.
You have to remove the image if the object is not TRUE
if (isTheObjectThere==TRUE) {
cell.favImg.image=[UIImage imageNamed:#"3081#3x.png"];
} else {
cell.favImg.image=nil;
}
Yes, you are right it's because of reusing your cells via dequeueReusableCell with identifier as-
dictionaryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
according to your requirements you set a star image on a cell to indicate some favorite elements on the respective cell, like this
BOOL isTheObjectThere = [self.favoriteArry containsObject:self.tableData[indexPath.row]];
if (isTheObjectThere==TRUE) {
cell.favImg.image=[UIImage imageNamed:#"3081#3x.png"];
}
When any cell with star image is reused than it should be removed if the next cell does not some favorite elements but if it does have some favorite elements than it should be used as-
To resolve this issue just add the else case with the above if statement as
if (isTheObjectThere == TRUE)
cell.favImg.image=[UIImage imageNamed:#"3081#3x.png"];
else
cell.favImg.image=nil;
I am using tableview apple's lazy loading code in my project,but having exception in project. And error is - *** Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:],here is my code please help.But it is working in other project.I have no delegate method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"LazyTableCell";
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell";
NSUInteger nodeCount = [self.entries count];
if (nodeCount == 0 && indexPath.row == 0)
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
cell.detailTextLabel.text = #"Loading…";
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nodeCount > 0)
{
AppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
cell.textLabel.text = appRecord.name;
if (!appRecord.appIcon)
{
if (self.mytable_view.dragging == NO && self.mytable_view.decelerating == NO)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
cell.imageView.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
cell.imageView.image = appRecord.appIcon;
}
}
return cell;
}
Because cellForRowAtIndexPath is returning a nil value and then configureCellForDisplay is expecting a UITableViewCell. The storyboard or XIB does not have a cell defined with the cell identifier you specified. Better check the spelling of identifier.
Please check for Delegate.
Have you added both delegate or not?
UITableViewDelegate, UITableViewDataSource
import UIKit
class UserFriendVC: UIViewController, UITableViewDelegate, UITableViewDataSource
{
override func viewDidLoad() {
super.viewDidLoad()
}
}
you should add cellIdentifier from "Show the attributes inspector". Please fallow just like below snippet.
Firstly added below code to your-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath delagate method.
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
ResultCustomTableViewCell *cell = (ResultCustomTableViewCell *)[resultTableView dequeueReusableCellWithIdentifier:#"ResultTableViewCellIdentifier"];
...
//set the cell property
...
return cell;
}
and then jump the "Show the attributes inspector", While selected cell root view.
And then paste the same identifier name to identifier section in "Show the attributes inspector". in this case i use this ResultTableViewCellIdentifier.
And one more think. if you use custom cell just like this scenario, you must add below delegate metod. Because your custom cell height can be higher or smaller original tableview height. And Also you should register this nib in viewDidLoad.
- (void)viewDidLoad {
[resultTableView registerNib:[UINib nibWithNibName:#"ResultCustomTableViewCell" bundle:nil] forCellReuseIdentifier:[ResultCustomTableViewCell reuseIdentifier]];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat height = 0.0;
if (tableView == resultTableView){
height = 44.0f;
}
return height;
}
i hope, it'll fix your problem
CellIdentifier I bet your cellForRowAtIndexPath is returning nil.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"LazyTableCell";
static NSString *PlaceholderCellIdentifier = #"PlaceholderCell";
NSUInteger nodeCount = [self.entries count];
if (nodeCount == 0 && indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:PlaceholderCellIdentifier] autorelease];
}
cell.detailTextLabel.text = #"Loading…";
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if (nodeCount > 0) {
AppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
cell.textLabel.text = appRecord.name;
if (!appRecord.appIcon)
{
if (self.mytable_view.dragging == NO && self.mytable_view.decelerating == NO)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
cell.imageView.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
cell.imageView.image = appRecord.appIcon;
}
}
return cell;
}
That's probably why [UITableView _configureCellForDisplay:forIndexPath:] is failing... because cellForRowAtIndexPath is returning a null value and then configureCellForDisplay is expecting a UITableViewCell.
Register your cell in the - (void)viewDidLoad method using
[self.tableView registerClass:UITableViewCell.class forCellReuseIdentifier:#"Your Reuse Identifier"];
if your are using storyboards and use this if you are using a custom cell.
[self.tableView registerNib:UINib nibWithNibName:#"Your File Name.xib" bundle:nil forCellReuseIdentifier:#"Your Reuse Identifier"]
I have data and image in cells of UITableView. I want to change image of a particular cell,
I have a code with each cell.
I am not able to find the way to iterate the tableview for cell.
here is snap shot of my tableview function.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellText = nil;
NSArray *keys = [[[self packageItems] allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
cellText = [keys objectAtIndex:[indexPath row]];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
cell.imageView.image=[UIImage imageNamed:#"checkbox.png"];
//cell.imageView.image=[UIImage imageNamed:#"checkbox-checked.png"];
return cell;
}
There is another function where i want to change cell image to cell.imageView.image=[UIImage imageNamed:#"checkbox-checked.png"];
- (void)OnAction
{
static NSString *CellIdentifier = #"Cell";
NSIndexPath *indexPath = [[NSIndexPath alloc] initWithIndex:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath ];
cell.imageView.image=[UIImage imageNamed:#"checkbox-checked.png"];
}
If you wont to change something in table view with you function you dont have to make new cell, just modify actual cell. Just make condition in your cellForRowAtIndexPath delegate:
if(indexPath == indexToModify) {
cell.imageView.image=[UIImage imageNamed:#"checkbox-checked.png"];
} else {
cell.imageView.image=[UIImage imageNamed:#"checkbox.png"];
}
and in your - (void)OnAction method use in the end:
[self.tableView reloadData];