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"]
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.
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'm confused as to what the problem/difference is with this code. In the first working example, I'm loading the table view from a custom class. This works dandy.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EventCell";
ISEventsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithWhite:.2 alpha:.7];
ISSingleEvent *singleEvent = events[indexPath.row];
[cell populateWithEvents:(singleEvent)];
return cell;
}
Now I want to add a second section to the table view and everything seems to be going fine until I add the conditions for cellForRowAtIndexPath. I get the error "No visible interface for 'UITableViewCell' declares the selector 'populateWithPasses:'
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"EventCell";
static NSString *CellIdentifier2 = #"FlareCell";
NSString *identityString = #"";
switch ([indexPath section]) {
case 0: {
identityString = CellIdentifier1;
break;
}
case 1: {
identityString = CellIdentifier2;
break;
}
default:
break;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identityString];
if ([indexPath section] == 0) {
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2
reuseIdentifier:CellIdentifier1];
cell.backgroundColor = [UIColor colorWithWhite:.2 alpha:.7];
ISSingleEvent *singleEvent = events[indexPath.row];
// Error here (below) "No visible interface for 'UITableViewCell' declares the selector 'populateWithEvents:'
[cell populateWithEvents:(singleEvent)];
}
} else {
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier2];
cell.backgroundColor = [UIColor colorWithWhite:.2 alpha:.7];
ISFlareEvent *singleEvent = flareEvents[indexPath.row];
// Error here (below) "No visible interface for 'UITableViewCell' declares the selector 'populateWithFlares:'"
[cell populateWithFlares:(singleEvent)];
}
}
return cell;
}
So what am I doing wrong here? When I called "populateWithEvents" with only one section, it didn't throw an error. Now I've set up two section, each with it's own tableviewcell and it's just not working. Any help would be greatly appreciated.
Thanks,
just cast your cell like this
[(ISEventsCell *)cell populateWithFlares:(singleEvent)];
You are trying to call populateWithFlares: for UITableviewCell. The metho is defined for ISEventsCell
I have 2 tableViews, the first only loads a list from an array.
The other 1, show details per row. But it shows a crash report:
'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath: Exception'
What seems to be wrong with my code? I want to show each row a different detail that came from the same sqlite row.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
//tableView 1
if(tableView == self.cTableLabel)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"courseCell"];
NSLog(#"Here.");
Course *courses = [self.course objectAtIndex:indexPath.row];
cell.textLabel.text =courses.cName;
cell.detailTextLabel.text =courses.cSchool;
return cell;
}
//tableView 2
if(tableView == self.jTableLabel)
{
if (indexPath.row == 0)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"JobName"];
cell.textLabel.text = _jDetails.jName;
}
else if (indexPath.row == 1)
{
cell= [tableView dequeueReusableCellWithIdentifier:#"JobEarnings"];
cell.textLabel.text = #"Job Earnings (per month): Php";
cell.detailTextLabel.text = _jDetails.jEarnings;
}
return cell;
}
return 0;
}
For performance reasons, a table view's data source should generally reuse UITableViewCell objects when it assigns cells to rows in its tableView:cellForRowAtIndexPath: method. A table view maintains a queue or list of UITableViewCell objects that the data source has marked for reuse. Call this method from your data source object when asked to provide a new cell for the table view. This method dequeues an existing cell if one is available or creates a new one using the class or nib file you previously registered. If no cell is available for reuse and you did not register a class or nib file, this method returns nil.
If you registered a class for the specified identifier and a new cell must be created, this method initializes the cell by calling its initWithStyle:reuseIdentifier: method. For nib-based cells, this method loads the cell object from the provided nib file. If an existing cell was available for reuse, this method calls the cell’s prepareForReuse method instead.
You need to create different cells for each tableview, Try to use the above code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
//tableView 1
if(tableView == self.cTableLabel)
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
else
{
for(UIView *view in cell.contentView.subviews)
{
[view removeFromSuperview];
}
}
NSLog(#"Here.");
Course *courses = [self.course objectAtIndex:indexPath.row];
cell.textLabel.text =courses.cName;
cell.detailTextLabel.text =courses.cSchool;
return cell;
}
//tableView 2
if(tableView == self.jTableLabel)
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
else
{
for(UIView *view in cell.contentView.subviews)
{
[view removeFromSuperview];
}
}
if (indexPath.row == 0)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"JobName"];
cell.textLabel.text = _jDetails.jName;
}
else if (indexPath.row == 1)
{
cell= [tableView dequeueReusableCellWithIdentifier:#"JobEarnings"];
cell.textLabel.text = #"Job Earnings (per month): Php";
cell.detailTextLabel.text = _jDetails.jEarnings;
}
return cell;
}
return 0;
}
Please cross check either one of your table is returning more number of rows in numberOfRowsInSection method . It might be that you haven't put check on this method as both of the table are returning different number of rows .
First, check that your numberOfRowsInSection returns the correct number of rows for your table. I would think this would be it.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(tableView == self.cTableLabel)
{
return [self.course count];
}
//tableView 2
if(tableView == self.jTableLabel)
{
return 2;
}
return 0;
}
Otherwise I would set a break point on return 0; or NSLog before it in cellForRowAtIndexPath, because my guess is neither if block is hit and you are returning zero. Does it get triggered?
Edit - Ah, I think I see dequeueReusableCellWithIdentifier: will return a nil cell if you haven't set one up yet. Try using dequeueReusableCellWithIdentifier: forIndexPath: instead. This will always return a valid cell assuming you called registerClass:[UITableViewCell class] forCellReuseIdentifier: first.
Give this a shot:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"courseCell"];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"JobName"];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"JobEarnings"];
//tableView 1
if(tableView == self.cTableLabel)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"courseCell" forIndexPath:indexPath];
NSLog(#"Here.");
Course *courses = [self.course objectAtIndex:indexPath.row];
cell.textLabel.text =courses.cName;
cell.detailTextLabel.text =courses.cSchool;
return cell;
}
//tableView 2
if(tableView == self.jTableLabel)
{
if (indexPath.row == 0)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"JobName" forIndexPath:indexPath];
cell.textLabel.text = _jDetails.jName;
}
else if (indexPath.row == 1)
{
cell= [tableView dequeueReusableCellWithIdentifier:#"JobEarnings" forIndexPath:indexPath];
cell.textLabel.text = #"Job Earnings (per month): Php";
cell.detailTextLabel.text = _jDetails.jEarnings;
}
return cell;
}
return 0;
}
Also registerClass:[UITableViewCell class] forCellReuseIdentifier: could be called in your init, it only needs to be declared once.
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.