Invalid TableView Update - ios

I have 1 empty section and other sections with full of objects.I have a button in all rows.when clicked on the button in a row the row should move to the empty section.But I am getting this error saying invalid tableview update.
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source.'
I tried the following Code.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if ([[arrayForBool objectAtIndex:section] boolValue]) {
if(section == 0){
return favouritesArray.count;
}else{
NSString* key = [sectionTitleArray objectAtIndex:section - 1];
NSArray *aArray = [sectionContentDict valueForKey:key];
return aArray.count;
}
}
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"UCPMenuCellIdentifier";
UCPCategoryListCell *cell = (UCPCategoryListCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UCPCategoryListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]autorelease];
}
if(indexPath.section == 0){
cell.textLabel.text = [favouritesArray objectAtIndex:indexPath.row ];
}
else{
NSString* key = [sectionContentDict.allKeys objectAtIndex:indexPath.section - 1];
BOOL manyCells = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
if (!manyCells) {
cell.textLabel.text = #"click to enlarge";
}
else{
cell.textLabel.text = [[sectionContentDict objectForKey:key] objectAtIndex:indexPath.row];
}
}
UIButton *deletebtn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
deletebtn.frame=CGRectMake(220, 10, 20, 20);
[deletebtn addTarget:self action:#selector(moveRowToFavorites:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:deletebtn];
return cell;
}
-(void)moveRowToFavorites:(id)sender{
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
[self.aTableView beginUpdates];
[favouritesArray addObject:cell.textLabel.text];
NSIndexPath *newindexPath = [NSIndexPath indexPathForRow:[favouritesArray count] inSection:0];
NSIndexPath *oldindexPath = [self.aTableView indexPathForCell:cell];
[self.aTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:oldindexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.aTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newindexPath] withRowAnimation:UITableViewRowAnimationRight];
[self.aTableView endUpdates];
}

Try moveRowToFavorites: method like this:
- (void) moveRowToFavorites: (id) sender
{
UIButton* button = (UIButton*) sender;
UITableViewCell* cell = (UITableViewCell*) button.superview.superview;
[self.aTableView beginUpdates];
[favouritesArray addObject: cell.textLabel.text];
NSIndexPath* newindexPath = [NSIndexPath indexPathForRow: [favouritesArray count] - 1
inSection: 0];
[self.aTableView insertRowsAtIndexPaths: [NSArray arrayWithObject: newindexPath]
withRowAnimation: UITableViewRowAnimationRight];
NSIndexPath* oldindexPath = [self.aTableView indexPathForCell: cell];
[self.aTableView deleteRowsAtIndexPaths: [NSArray arrayWithObject: oldindexPath]
withRowAnimation: UITableViewRowAnimationFade];
NSInteger oldSection = oldindexPath.section;
NSInteger oldRow = oldindexPath.row;
NSString* key = [sectionTitleArray objectAtIndex: oldSection - 1];
NSMutableArray* anArray = [NSMutableArray arrayWithArray: [sectionContentDict valueForKey: key]];
[anArray removeObjectAtIndex: oldRow];
[sectionContentDict setValue: anArray forKey: key];
[self.aTableView endUpdates];
}
I created project with this code. It is working fine. If you need I can give.
Hope my code helps you.

In moveRowToFavorites method change arrays(favouritesArray and sectionContentDict). You have added in favouritesArray. Delete same object from other array. Then call table reloadData.
Try this. It will add to favorite section.
-(void)moveRowToFavorites:(id)sender{
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
[favouritesArray addObject:cell.textLabel.text];
//here you need to delete same object from [sectionContentDict objectForKey:key]
[self.aTableView reloadData];
}
Dont do anything like insertRowsAtIndexPaths or deleteRowsAtIndexPaths

In -(void)moveRowToFavorites:(id)sender after just adding object to favouritesArray, you have to remove objet from array within the sectionContentDict. And you dont have to use [table reloadData] after begin-end Updates.

Related

Error within tableview when cells are switching sections

So in my table view, I have an array called dataArray and it's getting its objects from a server using JSON. I added a button to each cell and when the button is clicked the cell is supposed to move to another section/ or another array called followedArray to be more exact. Now the cells are transferring to the other section but after moving 6 cells I get an error that saids this. All arrays are NSMutableArray. Also, I'm new to iOS so try to work with me, thank you.
2016-10-26 17:27:19.569 CustomCellApp[3212:198103] * Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 6 beyond bounds [0 .. 4]'
---------------------
Side note, I can make a separate error post but I have another issue, the images displaying in the cells are being changed to other images when switching sections, using the pod SDWebImage.
---------------------
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (!isFiltered) {
if (section == 0) {
return [followedArray count];
}
else if (section == 1) {
return [dataArray count];
}
}
return [filteredArray count];
}
---------------------
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
return #"Followed Data";
}
else {
return #"All Data";
}
}
---------------------
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configuring the cell
Data * dataObject;
if (!isFiltered) {
if (indexPath.section == 0) {
dataObject = [followedArray objectAtIndex:indexPath.row];
}
else if (indexPath.section == 1) {
dataObject = [dataArray objectAtIndex:indexPath.row];
}
}
else {
dataObject = [filteredArray objectAtIndex:indexPath.row];
}
// Loading Images
if (!isFiltered) {
// Exception Breakpoint Here
NSURL * imgURL = [[dataArray objectAtIndex:indexPath.row] valueForKey:#"dataURL"];
[cell.myImageView setContentMode:UIViewContentModeScaleAspectFit];
[cell.myImageView sd_setImageWithURL:imgURL placeholderImage:[UIImage imageNamed:#"no-image.png"] options:SDWebImageRefreshCached];
}else{
NSURL * imgURL = [[filteredArray objectAtIndex:indexPath.row] valueForKey:#"dataURL"];
[cell.myImageView setContentMode:UIViewContentModeScaleAspectFit];
[cell.myImageView sd_setImageWithURL:imgURL placeholderImage:[UIImage imageNamed:#"no-image.png"] options:SDWebImageRefreshCached];
}
// Loading Follow Button
cell.followButton.tag = indexPath.row;
[cell.followButton addTarget:self action:#selector(followButtonClick:) forControlEvents:UIControlEventTouchUpInside];
cell.followButton.hidden = NO;
return cell;
}
---------------------
-(void)followButtonClick:(UIButton *)sender {
// Adding row to tag
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.myTableView];
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:buttonPosition];
// Creating an action per tag
if (indexPath != nil)
{
// Change Follow to Following
[sender setImage:[UIImage imageNamed:#"follow.png"] forState:UIControlStateNormal];
cell.followButton.hidden = YES;
cell.followedButton.hidden = NO;
// ----- ERROR BEGINS HERE ----- //
[self.myTableView beginUpdates];
// ----- Inserting Cell to Section 0 ----- *CAUSING PROBLEMS*
// Exception Breakpoint Here
[followedArray addObject:[dataArray objectAtIndex:indexPath.row]];
[myTableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:followedArray.count-1 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
NSLog(#"indexPath.row = %ld", (long)indexPath.row);
// ----- Removing Cell from Section 1 ----- *WORKING*
[dataArray removeObjectAtIndex:indexPath.row];
NSInteger rowToRemove = indexPath.row;
[self.myTableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObjects:[NSIndexPath indexPathForRow:rowToRemove inSection:1], nil] withRowAnimation:YES];
NSLog(#"Array =%#",followedArray);
[self.myTableView endUpdates];
// ----- ERROR ENDS HERE ----- //
}
}
---------------------
This is what helped me fix the errors I was having. Credits to #AliOmari for helping me out.
In cellForRowAtIndexPath
// Configuring the cell
Data * dataObject;
if (!isFiltered) {
if (indexPath.section == 0) {
dataObject = [followedArray objectAtIndex:indexPath.row];
[cell populateCell:dataObject isFollowed:YES indexPath:indexPath parentView:self];
}
else if (indexPath.section == 1) {
dataObject = [dataArray objectAtIndex:indexPath.row];
[cell populateCell:dataObject isFollowed:NO indexPath:indexPath parentView:self];
}
}
else {
dataObject = [filteredArray objectAtIndex:indexPath.row];
[cell populateCell:dataObject isFollowed:NO indexPath:indexPath parentView:self];
}
return cell;
Inside my Button
[self.myTableView beginUpdates];
// ----- Inserting Cell to Section 0 -----
[followedArray insertObject:[dataArray objectAtIndex:indexPath.row] atIndex:0];
[myTableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
//NSLog(#"indexPath.row = %ld", (long)indexPath.row);
// ----- Removing Cell from Section 1 -----
[dataArray removeObjectAtIndex:indexPath.row];
NSInteger rowToRemove = indexPath.row;
[self.myTableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObjects:[NSIndexPath indexPathForRow:rowToRemove inSection:1], nil] withRowAnimation:YES];
//NSLog(#"Array =%#",followedArray);
[self.myTableView endUpdates];

Deselect a row of tableview search results

I have a table view which list countries and I can select multiple raws. I've the option of select and deselect raws. The problem comes when I add a Search bar, I can`t deselect a raw of the results list because the method "didDeselectRowAtIndexPath" is never called when I press a results item.
I searched about this problem but nothing,
Thanks in advance,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
//[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:indexPath.row];
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = NO;
tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
NSDictionary *country = [self.searchResult objectAtIndex:indexPath.row];
[self.selectedItems addObject: country];
}
else
{
//[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:indexPath.row];
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = NO;
tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
NSDictionary *country = [self.countriesArray objectAtIndex:indexPath.row];
[self.selectedItems addObject: country];
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
//[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = YES;
tableViewCell.accessoryType = UITableViewCellAccessoryNone;
NSDictionary *country = [self.searchResult objectAtIndex:indexPath.row];
[self.selectedItems removeObject:country];
}else
{
//[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = YES;
tableViewCell.accessoryType = UITableViewCellAccessoryNone;
NSDictionary *country = [self.countriesArray objectAtIndex:indexPath.row];
[self.selectedItems removeObject:country];
}
}

How to code PrepareForSeque in UITableView that has sections and searching

I have constructed a nice TableView that contains sections, searching, and the alphabetical strip on the right.
I tested it and all seemed well until I noticed that anything after the "A"s was not working correctly. I discovered the reason - in my PrepareForSegue I was passing the object I found at the row, but not paying any attention to the sections.
I searched stack overflow and found some things like I am trying to do, but it seems they are coding in the didSelectRowAtIndexPath, no prepare for segue. And I was unable to get any of the code to work.
My first question is what is the relationship between the two methods? I am using Storyboards so I think I should stick with the segues. But then how do I find out which employee object to pass?
Any help would be greatly appreciated.
Bryan
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
employee *dtlEmployee = [_employees objectAtIndex:indexPath.row];
self.detailViewController.detailItem = dtlEmployee;
}
else
{
// employee *dtlEmployee;
//
// int row = indexPath.row;
// int section = indexPath.section;
//
// NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:row inSection:section];
//
// [self.tableView deselectRowAtIndexPath:newIndexPath animated:NO];
// UITableViewCell *cell = [tableView cellForRowAtIndexPath:newIndexPath];
//
// dtlEmployee = [_employees objectAtIndex:newIndexPath];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
employee *dtlEmployee;
// int row = [[self.tableView] indexPath.row];
// int section = [self.tableView indexPath.section];
// NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:row inSection:section];
// dtlEmployee = [_employees objectAtIndex:newIndexPath];
// NSIndexPath *selectedRowIndexPath = [self.tableView indexPathForSelectedRow];
// NSUInteger selectedRow = selectedRowIndexPath.row;
// NSUInteger selectedSection = selectedRowIndexPath.section;
// NSArray *tmpArray = [_employees objectAtIndex:[self.tableView indexPathForSelectedRow]];
// dtlEmployee = [tmpArray objectAtIndex:selectedRowIndexPath.row];
// dtlEmployee = [tmpArray objectAtIndex:indexPath.row];
//
// dtlEmployee = [_employees objectAtIndex:selectedRowIndexPath.]
//
if (isSearching)
{
dtlEmployee = [self.filteredEmployees objectAtIndex:self.searchDisplayController.searchResultsTableView.indexPathForSelectedRow.row];
}
else
{
dtlEmployee = [_employees objectAtIndex:[self.tableView indexPathForSelectedRow].row];
}
[[segue destinationViewController] setDetailItem:dtlEmployee];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [self.tableView dequeueReusableCellWithIdentifier: CellIdentifier];
//cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if (isSearching)
{employee *thisEmployee = [self.filteredEmployees objectAtIndex:indexPath.row];
cell.textLabel.text = thisEmployee.fullName;}
else
{employee *thisEmployee = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = thisEmployee.fullName;}
return cell;
}
Assuming that your segue is connected to the table view cell, your sender in prepareForSegue: is actually a cell. (Use logging or the debugger to be sure.)
That means you can ask your table view for an index path that matches the cell and use the same logic that you would have in tableView:cellForRowAtIndexPath: for obtaining an object from a path.
Your logic for getting the right employee in tableView:cellForRowAtIndexPath: looks like this:
if (isSearching)
{
employee *thisEmployee = [self.filteredEmployees objectAtIndex:indexPath.row];
cell.textLabel.text = thisEmployee.fullName;
}
else
{
employee *thisEmployee = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = thisEmployee.fullName;
}
But your logic in prepareForSegue:sender: looks like this:
if (isSearching)
{
dtlEmployee = [self.filteredEmployees objectAtIndex:self.searchDisplayController.searchResultsTableView.indexPathForSelectedRow.row];
}
else
{
dtlEmployee = [_employees objectAtIndex:[self.tableView indexPathForSelectedRow].row];
}
You need to make the logic when performing the segue match the one when populating the cell, which from the sound of it works correctly. It appears that you're doing it correctly when isSearching is true, so when it's not true, the following line should be used:
employee *thisEmployee = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex: [self.tableView indexPathForSelectedRow].section]] objectAtIndex: [self.tableView indexPathForSelectedRow].row];

delete last row in TableView and show a "no results" label in new cell

I have a problem with my UITableView where deleting the last row in the section terminates the app with an NSInternalInconsistencyException:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
My UITableView is populated with MPMediaItems from an MPMediaItemCollection (self.detailCollection). When the last one gets deleted I want to show a "No results found" label in a blank cell.
Here is my cellForRowAtIndexPath:
- (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] autorelease];
}
// Configure the cell...
if ([[self.detailCollection items] count] == 0) {
[tableView numberOfRowsInSection:1];
cell.textLabel.text = #"No results found";
//return cell;
} else {
MPMediaItem *song = (MPMediaItem *)[[self.detailCollection items] objectAtIndex:[indexPath row]];
if (song) {
cell.textLabel.text = [song valueForProperty:MPMediaItemPropertyTitle];
MPMediaItemArtwork *art = [song valueForProperty:MPMediaItemPropertyArtwork];
cell.imageView.image = [art imageWithSize:CGSizeMake(64, 64)];
}
}
return cell;
}
Here is my code for deleting the rows:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
PlaylistData *pData = [PlaylistData getInstance];
NSMutableArray *tempArray = [[self.eventDictionary valueForKey:[NSString stringWithFormat:#"%#", pData.selectedEvent]] mutableCopy];
NSMutableArray *newArray = [[NSMutableArray alloc] init];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
// Delete the row from the data source
[tempArray removeObjectAtIndex:indexPath.row];
[self.eventDictionary setValue:tempArray forKey:[NSString stringWithFormat:#"%#", pData.selectedEvent]];
[[NSUserDefaults standardUserDefaults] setValue:self.eventDictionary forKey:#"Playlist Items"];
[[NSUserDefaults standardUserDefaults] synchronize];
if ([tempArray count] == 0) {
[tableView numberOfRowsInSection:1];
}
for (int i=0; i<[tempArray count]; i++) {
NSString *pID = [NSString stringWithFormat:#"%#", [tempArray objectAtIndex:i]];
unsigned long long ullvalue = strtoull([pID UTF8String], NULL, 0);
NSNumber *UniqueID = [NSNumber numberWithUnsignedLongLong:ullvalue];
MPMediaQuery *cellQuery = [[MPMediaQuery alloc] init];
[cellQuery addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:UniqueID forProperty:MPMediaItemPropertyPersistentID]];
for (MPMediaItem *item in [cellQuery items]) {
[newArray addObject:item];
}
[cellQuery release];
}
if (![newArray count] == 0) {
self.detailCollection = [[MPMediaItemCollection alloc] initWithItems:newArray];
[tableView numberOfRowsInSection:[self.detailCollection count]];
} else {
[tableView numberOfRowsInSection:1];
[tableView reloadData];
}
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
And here is my numberOfRowsInSection:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if ([[self.detailCollection items] count] == 0 || [self.detailCollection items] == nil || [self.detailCollection items] == NULL) {
return 1;
}
return [[self.detailCollection items] count];
}
My question is: Why isn't it creating the "No results found" cell when self.detailCollection is == 0?
I think you want something to the effect of:
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
if ([newArray count] == 0) {
[tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[tableView endUpdates];
However, a simpler solution would be to just add a label to your table view. Unless there is some specific reason that you need an actual UITableViewCell to display "No results found".
UILabel *label = [[UILabel alloc] init];
CGRect frame = CGRectMake(0.0, 0.0, 320.0, 44.0);
label.frame = frame;
label.text = #"No results found";
[self.tableView addSubview:label];
One solution that I would recommend is to use a table footer view rather than a new cell. Basically, add a footer to your table that is only visible when the cell count is 0.
You can override the method
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
to get a footer.
When deleting and adding objects, check the new count and then adjust the visibility of the footer from there.
You are calling numberOfRowsInSection in a couple of places. You should never be calling it, it's a call back hook that you implement and the system calls.
The cleanest solution to do this would be to set self.tableView.tableFooterView when rows = 0
#interface UITableView : UIScrollView <NSCoding> {
...
#property(nonatomic,retain) UIView *tableFooterView;
// accessory view below content. default is nil. not to be confused with section footer

CoreData with relationship in the same UItableView

I need to load the "Main Entity" that has a relationship one-to-many with "Child Entity" into the same UITableView, how can i do?
Thanks in advance.
Update
i use the following code to populate the UITableView:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[[fetchedResultsController sections] objectAtIndex:section] name];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
if (self.selectedIndexPath) {
return [sectionInfo numberOfObjects] + [self.childArray count];
}else {
return [sectionInfo numberOfObjects];
}
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
OreRecupero *selectedObj=(OreRecupero*)[self.fetchedResultsController objectAtIndexPath:indexPath];
OrarioMainCell *cell = nil;
if (indexPath == self.selectedIndexPath) {
NSUInteger giorniCount = [selectedObj.giorni count];
NSInteger row = indexPath.row;
if (indexPath.row < giorniCount) {
cell = (OrarioMainCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell=(OrarioMainCell *)[[[NSBundle mainBundle]loadNibNamed:#"myCustomCell" owner:self options:nil]objectAtIndex:11];
radiusLabel=[[LabelRadiusAndText alloc]init];
}
UIImageView *bgImage=[[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"fondoCella"]]autorelease];
cell.backgroundView=bgImage;
[df setDateFormat:#"HH:mm"];
cell.textLabel.text = [NSString stringWithFormat:#"%# - %#",[df stringFromDate:selectedObj.oraInizio],[df stringFromDate:selectedObj.oraFine]];
} else {
cell = (OrarioMainCell *)[tableView dequeueReusableCellWithIdentifier:#"DetailCell"];
if (cell == nil) {
cell=(OrarioMainCell *)[[[NSBundle mainBundle]loadNibNamed:#"myCustomCell" owner:self options:nil]objectAtIndex:13];
radiusLabel=[[LabelRadiusAndText alloc]init];
}
GiornoRecupero *giorno = [childArray objectAtIndex:row];
cell.textLabel.text = [NSString stringWithFormat:#"%i", giorno.oreStraordinario];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%i", giorno.durata];
}
} else {
cell = (OrarioMainCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell=(OrarioMainCell *)[[[NSBundle mainBundle]loadNibNamed:#"myCustomCell" owner:self options:nil]objectAtIndex:11];
radiusLabel=[[LabelRadiusAndText alloc]init];
}
UIImageView *bgImage=[[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"fondoCella"]]autorelease];
cell.backgroundView=bgImage;
[df setDateFormat:#"HH:mm"];
cell.orariLbl.text = [NSString stringWithFormat:#"%# - %#",[df stringFromDate:selectedObj.oraInizio],[df stringFromDate:selectedObj.oraFine]];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
OreRecupero *selectedObj=(OreRecupero*)[self.fetchedResultsController objectAtIndexPath:indexPath];
NSIndexPath *dropDownCellIndexPath = [NSIndexPath indexPathForRow:indexPath.row + 1
inSection:indexPath.section];
//if user tapped the same row twice let's start getting rid of the control cell
if (!self.selectedIndexPath) {
// Show Drop Down Cell
for (GiornoRecupero *giorno in selectedObj.giorni) {
[self.childArray addObject:giorno];
}
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:dropDownCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
self.selectedIndexPath = indexPath;
} else {
NSIndexPath *currentdropDownCellIndexPath = [NSIndexPath indexPathForRow:self.selectedIndexPath.row + 1
inSection:self.selectedIndexPath.section];
if (indexPath.row == self.selectedIndexPath.row) {
// Hide Drop Down Cell
[self.childArray removeAllObjects];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:currentdropDownCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
self.selectedIndexPath = nil;
} else if (indexPath.row == currentdropDownCellIndexPath.row) {
// Dropdown Cell Selected - No Action
return;
} else {
// Switch Dropdown Cell Location
[self.myTableView beginUpdates];
// Hide Dropdown Cell
[self.childArray removeAllObjects];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:currentdropDownCellIndexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
// Show Dropdown Cell
NSInteger dropDownCellRow = indexPath.row + ((indexPath.row >= currentdropDownCellIndexPath.row) ? 0 : 1);
dropDownCellIndexPath = [NSIndexPath indexPathForRow:dropDownCellRow
inSection:indexPath.section];
for (GiornoRecupero *giorno in selectedObj.giorni) {
[self.childArray addObject:giorno];
}
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:dropDownCellIndexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
self.selectedIndexPath = [NSIndexPath indexPathForRow:dropDownCellIndexPath.row - 1
inSection:dropDownCellIndexPath.section];
[self.myTableView endUpdates];
}
}
}
i would like to insert new rows using didSelectRowAtIndexPath method, getting data from "Child Entity"

Resources