UITableView delete and reload cells - objective-c

I am delete some rows in UITableView like this:
[tableView deleteRowsAtIndexPaths:toDelete withRowAnimation:UITableViewRowAnimationAutomatic];
This adds a nice animation to the delete operation.
However, after deleting I need to update all the currently visible rows. Calling
[tableView reloadData];
right after the first call works, but the nice animation effect is gone. What's a better way to do this? i.e., to animate the delete operation, and update all the currently visible rows?
Thanks!
The reason why I need to do this is because each cell contains a 'checkbox'. My view controller is checkbox's delegate and each checkbox has an NSIndexPath associated with it. When the checkbox is toggled, delegate is called telling it hey we toggled for x index path. Now, if some rows are deleted, the index paths need to be update. That's why I need to reload everything so each checkbox knows where it belongs.

In your deletion action use the performBatchUpdates instead of [tableView beginUpdates] this allows you to have a completion block
Animates multiple insert, delete, reload, and move operations as a
group.
self.tableView.performBatchUpdates({
//do stuff then delete the row
self.tableView.deleteRows(at: [indexPath], with: .fade)
}, completion: { (done) in
//perform table refresh
self.tableView.reloadData()
})

ctrahey's animation block doesn't work for me no matter what duration is passed. I have researched the mechanism of UITableView's delete, insert & reload. I am maintaining my project in Github countering this problem.
https://github.com/VansonLeung/VanTableController
It includes a working unit test in it. Normally in order to animate UITableView's cell animation, we have to do something like this:
[tableView_ beginUpdates];
[tableView_ deleteRowsAtIndexPaths: indexPathDelete withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView_ insertRowsAtIndexPaths: indexPathInsert withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView_ reloadRowsAtIndexPaths: indexPathReload withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView_ endUpdates];
We have to determine the delete rows, insert rows & reload rows' indexPath arrays and it's a very nasty work! My project work is basically a wrapper for generating these indexPaths.

Note: As noted in comments, it is likely that this answer will not work. If it were not accepted, I would delete it.
I'm not 100% sure that this is the best way to do this, but there is something pleasantly clean about it. We can wrap reloadData in a regular UIView animation block after modifying the underlying model:
// if self.people is a mutable array
[self.people removeObjectAtIndex:13];
[UIView animateWithDuration:0.5 animations:^{
[self.tableView reloadData];
}];

I had some problems related to it. Using fixed index probably you will face a lot of headache. I've solved this adding to the UITableViewCell a reference to a Item from my datasource, not a NSIndexPath. So, there is no need to use indexPath saved into your cell.
Also, there is some information on Apple's Website saying we mustn't use the method reloadData inside insert or delete methods.
Apple docs
all this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view's delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates and endUpdates

Related

UITableView not drawing Cells correctly "sometimes"

When my app displays the table, sometimes, it displays ALL the content of the database. but when i try to segue to another VC an return from that VC (Lets say, I added a new entry to the Database), it displays this. if you touch below the "Missing" cells, it segue to the correct entry though...
I've already tried using:
[self.cTableView setNeedsDisplay];
[self.cTableView setNeedsLayout];
or
[self.cTableView beginUpdates];
[self.cTableView endUpdates];
or
[self.cTableView reloadData];
but still to no avail. Is there any way of refreshing the tableview graphically?
I can't post images due to reputations but the image that I'm going to post looks like the TableView gets CUT going down.
Image:
https://dl.dropboxusercontent.com/u/1336061/StackOverflow/Untitled.jpg
Are you re-using your cell correctly?
Check the cells reuse identifier. see that the cells are not being allocated every iteration (in cellForRow delegate).
If the objects that provide data to the "Data Source" of the table change, you might as well need to call:
[table reloadData];
OR
Load the new elements with their indexes (look at the UITableView headers to use the right delegate.

Reloading subview (UICollectionview)

In my ViewController I have four subviews, i.e UITableView, UICollectionView, View with UILabels, and View that displays preview image for that item.
By selecting a row in tableview, I am able to change preview image and all labels. However I can not refresh the UICollectionView data. I tried this solution but it just removes and adds views and that changes the layout and preview image disappears.
All I want to do is refresh UICollectionView contents. Is there any simpler way to do this?
Have you tried [self.collectionView reloadData]; ?
To refresh only a portion of the UICollectionView you could also call this:
[self.collectionView reloadItemsAtIndexPaths:#[indexPath]]
where indexPath is the cell you want to reload. You could include multiple index paths in the array as well. To reload the entire first section you could call this:
NSIndexSet *sections = [NSIndexSet indexSetWithIndex:0];
[self.collectionView reloadSections:sections];
Assuming you have correctly hooked up your UICollectionView to a dataSource (UICollectionViewDataSource), you can call [myCollectionView reloadData] to make your collection view call your dataSource's methods (as below) to refresh itself:
– collectionView:numberOfItemsInSection:
– numberOfSectionsInCollectionView:
– collectionView:cellForItemAtIndexPath:
– collectionView:viewForSupplementaryElementOfKind:atIndexPath:

Table View Checkmark if Task Complete

I'm working in Objective C. I have a UITableViewController with about 25 cells that push to a UIViewController. When the user hits back, I want to see if the user entered the correct data for the given cell. (I have a working bool , we'll call it isCellComplete for now). If isCellComplete is true, I want to add a checkmark as the accessory to the cell. I've been trying to put the test in cellForRowAtIndexPath but that method does not seem to run and refresh the cells everytime the view appears. Anyone have suggestions?
You should look into the UITableView method reloadRowsAtIndexPaths:withRowAnimation:. This is much more elegant than reloading the whole table view. And if you don't want an animation, you can specify UITableViewRowAnimationNone and it will look just like reloadData but be much more efficient.
You should do the check in tableView:cellForRowAtIndexPath: and if the check passes, set the cell's accessory to UITableViewCellAccessoryCheckmark. Then when you tell the table view to reload the appropriate row(s), it'll automatically call tableView:cellForRowAtIndexPath: on the data source and update that cell.
You could just call
[self.tableView reloadData];
in
-(void) viewWillAppear:(BOOL)animated
And that will make cellForRowAtIndexPath be called again when the view appears

UITableView cell reverting to old data after [tableview reloadData] is called

I have a UITableView that has several cells of various heights. Each of the cells has itself a table of cells (here i am manually handling adding and deleting UIViews) that can be edited or deleted. The problem is that any time I edit one of the inner UIViews in one of the UITableViewCells, it is immediately reset to its original data that was given to it at instantiation when i call [tableView reloadData] on the tableview. If I don't call reload data, all the data looks great, but the height of the row is too large if i happened to have deleted a row from my UITableViewCell class. I've tried everything I can imagine, calling setNeedsDisplay, removing and re-adding to subview, and creating the cell every time, without using dequeueReusableCellWithIdentifier. None of these have done the trick.
Any idea what could possibly be going wrong??
Thanks so much!

Animate section footer changes in grouped UITableView

I know that you can animate insertions of table view cells and section but sometimes I need to change the footer text to one with a different text or to one that is 'nil'. I need to animate it when a UISwitch is toggled.
Right now I am using [tableView reloadData] but this is ugly and changes the section footer too sudden and without any animations. Apple somehow animates this for example when you turn on Personal Hotspot the section footer is slightly changed and this change is animated.
How can I achieve the same effect?
Assuming you've already written the code in -tableView:titleForFooterInSection: to adjust in response to the UISwitch, you could just send an empty update block to the table view to get it reload with animation.
[self.tableView beginUpdates];
[self.tableView endUpdates];