I have added two prototype cells to my table view named FeedItem and ButtonItem. And my cellForRowAtIndexPath looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if(indexPath.row != [feeds count] - 1)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"FeedItem"];
FeedItem *item = [feeds objectAtIndex:indexPath.row];
[self configureTextForCell:cell withFeedItem:item];
[self configureCheckmarkForCell:cell withFeedItem:item];
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:#"ButtonItem"];
}
return cell;
}
But my app crashes with this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
Can someone point what I am doing wrong ?
Related
I'm having some issues with a crash occurring when I change view controllers - Basically I have a VC that takes data from the user for a search - it then brings up a new VC with search results, displayed in a UITableView (not using a UITableViewController, just a TableView inside a regular UIViewController)
Crash Log:
2016-08-29 20:48:03.950 MyApp[2596:60877] *** Assertion failure in -[SearchResultsTable _configureCellForDisplay:forIndexPath:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.60.7/UITableView.m:7971
2016-08-29 20:48:03.961 MyApp[2596:60877] Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView (; layer = ; contentOffset: {0, 0}; contentSize: {375, 1128}>) failed to obtain a cell from its dataSource (; layer = ; contentOffset: {0, 0}; contentSize: {0, 0}>)'
*** First throw call stack:
I've read that this issue is caused by not returning a cell in your cellForRowAtIndexPath function, however i'm positive that my implementation will return a cell successfully. (I tested the code of the function somewhere else, and cell does in fact have a value, and is not nil.)
Code:
#property searchResultCell * cell;
-(UITableViewCell*)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
_cell = [self dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if (_cell == nil)
{
_cell = [[searchResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
[[_cell txtDate] setText:#"test"];
return _cell;
}
Having placed some breakpoints down, it appears that this section of code is never even executed, despite the UITableView class, delegate and dataSource being set correctly.
viewDidLoad for the Search Results VC ([self SpecifiedSerial] is set previously before the segue happens. It is an NSString*):
- (void)viewDidLoad
{
[super viewDidLoad];
_SearchResultsTableDelegate = [[searchResultsTable alloc] init:[self specifiedSerial]];
[[self SearchResultsTable] setDelegate:_SearchResultsTableDelegate];
[[self SearchResultsTable] setDataSource:_SearchResultsTableDelegate];
}
Declarations:
#property (weak, nonatomic) IBOutlet UITableView *SearchResultsTable;
#property searchResultsTable * SearchResultsTableDelegate;
If anyone could point me in the right direction here, it'd be much appreciated!
Use this code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
_cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
Instead of:
-(UITableViewCell*)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
_cell = [self dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
Edit:
Your numberOfRowsInSection and numberOfSectionsInTableView seems to be incorrect.
Try this code:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [[self searchedTrainSightings] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
_cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell" forIndexPath:indexPath];
if (_cell == nil)
{
_cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
[[_cell textLabel] setText:#"test"];
return _cell;
}
probably the reason is you are returning nil from cellForRowAtIndexPath method and failing to dequeue a reusable cell.
use code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
searchResultCell *cell;
cell = (searchResultCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil){
cell = [[searchResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
[[_cell txtDate] setText:#"test"];
return cell;
}
And just configure your cell selecting your custom cell giving cell identifier using storyboard see image.
Hope it helps.
I seriously doubt the delegate method which you are using. I have seen this version of cellForRowAtIndexPath method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Try this
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
_cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (_cell == nil)
{
_cell = [[searchResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
[[_cell txtDate] setText:#"test"];
return _cell;
}
I have tableview with searchDisplayController. When I search for some text I successfully display the results on screen. My problem arises when I want to add a cell to existing results. Adding a cell must be done when searchDisplayController is active.
That is:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableDictionary * dict ;
BOOL isSearchView = tableView == self.searchDisplayController.searchResultsTableView;
if (isSearchView) {
dict = [searchTasks objectAtIndex:indexPath.row];
[self.searchDisplayController.searchResultsTableView deselectRowAtIndexPath:indexPath
animated:YES];
}
else{
dict = [self.tasks objectAtIndex:indexPath.row];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Task * task = [self getsomeTask];
NSIndexPath * ip = [NSIndexPath indexPathForRow:indexPath.row+1
inSection:indexPath.section];
if (isSearchView) {
[searchTasks insertObject:task atIndex:ip.row];
[self.searchDisplayController.searchResultsTableView
insertRowsAtIndexPaths:#[ip]
withRowAnimation:UITableViewRowAnimationRight];
}
after this is executed, and after the last line insertRowsAtIndexPaths:#[ip],
the code executes:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.searchDisplayController.isActive) {
return [searchTasks count];
} else {
return [tasks count];
}
}
Which is fine and here it selects the first option which is true according to program logic. But the it crashed and after this execution it never calls
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
delegate function of UITableview.
And gives me error:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
I cannot understand the reason why it does not call the cellForRowAtIndexPath function after rowcount function.
Any suggestions?
This is my code and my error. I have 2 tableviews in a storyboard with 2 customcells. But I can't set cellforrowatindexpath method for table2:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if(tableView.tag==1){
static NSString *CellIndentifier = #"CustomCell";
CustomCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIndentifier];
if (cell==nil) {
cell=[[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIndentifier];
}
cell.text1Label.text=[moviesArray objectAtIndex:indexPath.row];
cell.text2Label.text=[moviesArraytext2 objectAtIndex:indexPath.row];
return cell;
}
else if (tableView.tag==2){
static NSString *CellIndentifier2 = #"CategoryCell";
CategoryCell *cell2=[tableView dequeueReusableCellWithIdentifier:CellIndentifier2];
if (cell2==nil) {
cell2=[[CategoryCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIndentifier2];
}
cell2.categoryLabel.text=[hotProgramByCatArray objectAtIndex:indexPath.row];
return cell2;
return nil;
and this is the error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell categoryLabel]: unrecognized selector sent to instance 0x8e7f560'
Make sure the outlets for the views on the custom cells are wired up to the cell itself and not the "File's Owner".
You can check this by looking at the Connections Inspector in Interface Builder.
I'm trying to add custom cells to a static UITableViewController. I use SWTableViewCell to get the swipable cell and I'm using a custom -xib for the cell layout.
I seems to work fine when I only need to use one cell, but when there are more then one I get this: Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
This happens when I use dequeueReusableCellWithIdentifier in the cellForRowAtIndexPath when the second cell should appear (when I begin to scroll).
Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.images = selectedReport.image;
imagesArray = [self.images.allObjects mutableCopy];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
[self.tableView registerNib:[UINib nibWithNibName:#"PictureCell" bundle:nil] forCellReuseIdentifier:#"PictureCell"];
}
- (NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger) section
{
if(section == 0){
return 10;
}else if(section == 1){
return imagesArray.count; //It is the second section which is dynamic
}
return 1;
}
- (UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath
{
static NSString* cellIdentifier = #"PictureCell";
if (indexPath.section == 0 || indexPath.section == 2)
{ //Takes the rows from the storyboard
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
else
{
NSLog(#"%i",indexPath.row);
NSLog(#"%i",indexPath.section);
PictureTableViewCell *cell = (PictureTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; //Crash here when indexPath.row == 1
[cell setCellHeight:cell.frame.size.height];
cell.containingTableView = tableView;
indexPath.section, indexPath.row];
Image *tempImage = imagesArray[indexPath.row];
cell.image.image = [UIImage imageWithData:tempImage.image];
cell.lblDescription.text = tempImage.image_description;
cell.rightUtilityButtons = [self rightButtons];
cell.delegate = self;
return cell;
}
}
I have checked that numberOfRowsInSection returns 2 when section == 1.
Thank you for any assistance!
Use this instead
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
or in viewDidLoad, register the class like
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"PictureCell"];
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PictureCell" forIndexPath:indexPath];
}
My app crashes when I try to insert a new entry. I received this error previously, and I was not able to fix it. Can anyone help?
Here is my error displayed in the console:
2013-09-14 15:41:00.370 Probation App[9919:907] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
*** First throw call stack:
(0x31fe82a3 0x39ccc97f 0x31f33b75 0xd7b81 0x33eb228d 0x33f34f81 0x328f6277 0x31fbd5df 0x31fbd291 0x31fbbf01 0x31f2eebd 0x31f2ed49 0x35af62eb 0x33e44301 0x542fd 0x3a103b20)
libc++abi.dylib: terminate called throwing an exception
and here is my code:
#pragma mark UITableViewDataSource Methods
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"cell"];
if( nil == cell)
{
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
if (indexPath.row <self.probationers.count)
{
Probationer *thisProbationer = [self.probationers objectAtIndex:indexPath.row];
cell.textLabel.text = thisProbationer.probationerName;
cell.detailTextLabel.text = thisProbationer.probationerID;
}
else
{
cell.textLabel.text = #"Add Probationer";
cell.textLabel.textColor = [UIColor lightGrayColor];
cell.editingAccessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
-(NSInteger)tableView: (UITableView *)tv numberOfRowsInSection:(NSInteger)section
{
NSInteger count = self.probationers.count;
if(self.editing)
{
count = count +1;
}
return count;
//return [self.probationers count];
}
//Deleting an Entry
-(void) tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle) editing forRowAtIndexPath: (NSIndexPath *) indexPath
{
if (editing == UITableViewCellEditingStyleDelete)
{
[self.probationers removeObjectAtIndex:indexPath.row];
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}
}
#pragma mark UITableViewDelegate Methods
-(void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Probationer *chosenProbationer = [self.probationers objectAtIndex:indexPath.row];
ProbationerController *detailedViewController = [[ProbationerController alloc]init];
detailedViewController.delegate = self;
detailedViewController.currentProbationer = chosenProbationer;
if (indexPath.row <self.probationers.count && !self.editing)
{
[self.navigationController pushViewController:detailedViewController animated:YES];
}
if (indexPath.row == self.probationers.count && self.editing)
{
AddProbationerController *addProbationer = [[AddProbationerController alloc] init];
[self.navigationController pushViewController:addProbationer animated:YES];
}
[tv deselectRowAtIndexPath:indexPath animated:YES];
//selectedIndexPath = indexPath;
//[self.navigationController pushViewController:detailedViewController animated:YES];
}
The number of rows should always come from the data source (the bit you have commented out //return [self.probationers count];). Don't try to just add to the number. Add to the data source and then refresh the table view.
The stack trace say it all. Its definitely because of you self.probationers array.
Why don't you NSLog the number of items in the array and the number of rows/sections in your tableview.
When you are trying to associate indexPath.row and self.probationers you have to make sure they match with number of elements.
Also follow the basics while accessing elements of array(as they are much prone to get exceptions)
Nil check for the accessing array.
Know the exact count of the array, by logging.
Make sure you are trying to access any objects more than the available array indexes.