Objective c - Deleting rows of a table view - objective-c

it's my first question in this awesome site. I've really searched a lot and yet find an answer to the next problem.
I have a table view with 9 cells. One of the cells has a switch button in it. When the switched button value changes, i want to delete 2 rows of the table view. I have written the next code:
- (IBAction)switchValueChanged:(id)sender {
NSLog(#"%#", ([switch isOn]) ? #"ON" : #"OFF");
NSArray *deleteIndexPaths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:1 inSection:0],
[NSIndexPath indexPathForRow:2 inSection:0],
nil];
UITableView *tableView = (UITableView *)self.view;
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
// I Have to change the number of rows in the section here.
[tableView endUpdates];
}
When i run this, I'm getting a problem relating to the number of rows in the section - this number has been changed so i need to change it. I really can't find how i change it, but i know where i have to change it (see code).
How can i do it? how can i call the method numberOfRowsInSection:NSInteger and set also the rows?
Thank you very much :)

The number of rows in the table is in your
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
You need this to match the new number of rows in the table
---- EDIT
This means that you will need to keep track of the number of rows in your table.
Start with this set to 9 and delete 2 every time you change the switch
- (IBAction)switchValueChanged:(id)sender {
NSLog(#"%#", ([switch isOn]) ? #"ON" : #"OFF");
// We are going to delete 2 rows
numberOfRows -= 2;
...
and in your numberOfRowsInSection instead of returning 9 each time, return the new number of rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return numberOfRows;
}

You should delete the data from the datasource not the table cells and then just to refresh the table view. At least this is how i would do the design.

You have to also delete the data from the datasource of the table view. The data source is any container that holds the actual data which is being displayed on the table view. Just deleting the row only deletes the visual item of the row, when tableview is reloaded - it will want to draw 9-2 rows....but since number of rows is still returning 9, it will throw an inconsistency exception and tell you why. See the log carefully.

Related

crash application while delete section from UITableView

In tableview I have many sections, on the top row of section I have a delete button, I want to do delete section after clicking button but its crashing please help me how can I do this?? here is the code...
//****** adding delete section button
CellButton *_sectionButton = (CellButton*)[cell viewWithTag:10];
_sectionButton.hidden = YES;
_sectionButton.indexPath = indexPath;
[_sectionButton addTarget:self action:#selector(sectionDeleteButton:) forControlEvents:UIControlEventTouchUpInside];
-(void)sectionDeleteButton: (id)sender
{
CellButton *_secbtn = (CellButton*)sender;
NSInteger sectionNumber = _secbtn.indexPath.section;
[self.tableView beginUpdates];
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionNumber] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
[self.tableView reloadData];
}
EDIT: The error messsage is:
Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableView.m:1054 2013-07-04 04:25:15.921 estimation[9025:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number of sections inserted or deleted (0 inserted, 1 deleted)
I guess the numberOfSectionsInTableView: returns the previous number of sections. You must make sure that what you tell the table view to do also happens in the data source. That is, if you delete a section, then the numberOfSectionsInTableView must also return a number one less than before. The same stands for cells and everything else. This is probably described in the error you get.
You have to manage your number of sections in numberOfSectionsInTableview: delegate method
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//#warning Incomplete method implementation.
// Return the number of rows in the section.
return [MLControl shared].arrBuyList.count;//1;//[MLControl shared].arrBuyList.count;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
// [tableView beginUpdates];
NSLog(#"indexPath.row=%ld,indexPath.se=%ld",(long)indexPath.row,(long)indexPath.section);
[[MLControl shared].arrBuyList removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[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
}
}
I met this problem, but the reason is different from yours.
When I add a section for the tableView, I reload data with this method, this also crash logging like yours:
[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
Why do I use this method to reload my table? If I only refresh cells, this works fine, but I forgot I want to change the sections. For more information: What is More reliable way to reload UITableView Data?

Insert rows with a custom cell into table view

In my tableView there is five rows that always exist in the table ,,, when I tap on one of them new three rows will appear under the tapped one.
If the first five rows is a default UITableViewCell ,,, I want the three cells also to be from another custom cell; so the main five cells will be different from the the secondary rows (three under the main cell).
Here is how I add the secondary rows :
In tableView delegate didSelectRowAtIndexPath :
NSInteger count = indexPath.row + 1;
NSMutableArray *newRows = [NSMutableArray array];//
self.expandedIndex = indexPath.row + 1;
self.tableExpanded = YES;
for(int i = 0; i < [self.numbers count]; i++)
{
NSIndexPath *path = [NSIndexPath indexPathForRow:count inSection:0];
[newRows addObject:path];
[self.myArray insertObject:[self.numbers objectAtIndex:i] atIndex:count];
count++;
}
[tableView insertRowsAtIndexPaths:newRows withRowAnimation:UITableViewRowAnimationTop];
The rows added but I want them to be from the custom cell that I want to create ,,, any ideas
This is what I would do. I would make newRows a property and then at the end of didSelectRowAt... I would call table refresh. Then in my cellForRowAtIndexPath check to see if the specific indexPath is in newRows, if it is use a different cell style:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
if ([self.newRows contains:indexPath]) {
// create custom cell
} else {
// create normal cell
}
return cell;
}
If this does not make sense let me know and I can elaborate.
Also note, you will have some interesting edge cases to handle. For example, if the user clicks on the 3rd cell and new cells are inserted into rows 4-6, and they later click on cell 2, adding new cells in rows 3-5, then the previous 4-6 cells will now be at rows 7-9. I am not sure how you are you are structuring your app so this may not be an issue (like maybe on one of the five cells can have subcells added at a time) but just realize that this is a possibility.

tableview won't update after adding objects to an array

I have a tableview inside a popover in my main view which is a web browser. Whenever the user visits a web page I want it to add the page to a list of recently visited websites. I have the code set up to add the URL as a string to the array that is the data source for the table view. The table view only shows the first site visited and won't show anything past that. However I know the sites are being added to the array because the array shows the Sites using NSLog statements after being added. However they still won't show up in the table. Can anyone help me?
EDIT:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [recentlyVisitedUrls count];
}
Also make sure you are returning the correct length of your array from – tableView:numberOfRowsInSection:
Try
[tableView reloadTable];
after you add the new data.
If you wan't animated updating, you can call:
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO]
If you need animation, it will be better read: Table View Programming Guide for iOS, you need Batch insert… part.
If you have a large table, [tableView reloadData] is probably not ideal. It'll also will reset your view to the beginning of the table, which may or may not be desirable. You might try something like this:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_model.recordCount - 1 inSection:0];
[_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
[_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
BTW, _model is the data delegate class for the table in the example.
Also, make sure the data delegate updates it's total count correctly before you insert, or your app will crash on the insertRowsAtIndexPaths.

Add rows to existing UITableView section

I am trying to get some sample code on how I would add rows to an existing UITableView. I am trying to use the insertRowsAtIndexPaths: function.
[tableView insertRowsAtIndexPaths:addindexes withRowAnimation:UITableViewRowAnimationTop];
Any ideas how these indexes work and how I can add to an existing section or, if I don't have a section, then create a new section?
You have to create an array of indexpaths as -
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
for example if you want to insert 2nd row in section 0 and already have 1 row in section 0 then create an index path for row 1 in section 0 and call the insertRowsAtIndexPaths on table view, it will insert 2nd row in section.
If there is no section in table view then you should use an int for data source to give no of sections in table view, in this use -
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return noOfSection; //here section is as int which is initially zero
}
and initially your int "noOfSection" will be zero then there will be no section in table, then when you want to add section increase your int value by 1 and call [tableView reloadData];
You need to handle these functions if you are gonna insert row and section in a table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return noOfSections;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[noOfRows objectForIndex:section] intValue];
}
also if you are updating your table view it is recommended that you use beginUpdates and endUpdates method.
this is how you insert new row and section.
noOfSections++;
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:3] withRowAnimation:UITableViewRowAnimationTop];
// update your array before calling insertRowsAtIndexPaths: method
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:1 inSection:2]]
withRowAnimation:UITableViewRowAnimationTop];
check the sample code provided by the apple.
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UITableView_Class/Reference/Reference.html

Deleting all table rows in a section

For my iPad project I need to be able to reload table rows.
This is how it should works, depend on some "id" selected from a popupview, i need to be able to reload table rows, table rows are dynamics and has a UITextField in it. I tried to use [self.tableView reload] but for some reason it does not update the rows correctly. Something like UITextField placeholder owned by previous "id" does not change. What I have in mind is to remove all cells in that specific section and reload the table with the new "id". When i do this i got this exception:
* 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 (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 3 deleted).'
The project code:
- (void)selectedArchiefID:(NSString *) value {
[self.popOverController dismissPopoverAnimated:YES];
// collects all available document indexfields
int rowCount = [indexDefinities count];
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
for (int curIndex=0; curIndex < rowCount; curIndex++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:curIndex inSection:0]];
}
// deletes rows
if ([indexPaths count] > 0) {
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
//[self.tableView deleteSections:0 withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; //crashes here
}
[self.tableView reloadData];
}
Any idea what i did wrong?
Looks like you forgot to change the data of the datasource of the tableview.
You can't just change the tableview layout.
If you want to remove a section, you have to remove this section from the datasource first.
You could do this the easy way, by removing the section in a NSMutableArray (which is your datasource).
Or you could write a big if then else monster that figures out how much sections (and rows) to return in numberOfSectionsInTableView: and tableView:numberOfRowsInSection:.
Doesn't matter how you do it, but you have to remove the data before you update the tableview.
One more thing, having both [self.tableView beginUpdates]; /*...*/ [self.tableView endUpdates]; and [self.tableView reloadData]; in one method is usually useless. THe latter would kill the animation effect you get from the first one.