Middle animation in grouped table view looks horrible - ios

I've found similar question, but there is no answer (sorry, answer just doesn't work).
So I have grouped table and I want to animate content update instead of doing [tableView reloadData].
I do that by using this piece of code:
// Data source already updated here, but reloadData wasn't called
[self.tableView beginUpdates];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationMiddle];
[self.tableView endUpdates];
I uploaded 2 examples of the animation:
Plain: http://cl.ly/3u1M3l1w3V3J (slow motion)
Grouped: http://cl.ly/1O3Z2M280n0z (slow motion)
As you can see difference is huge.
I don't change my code at all, just change tableView style in the storyboard.
Does it men that there is no other way then subclassing UITableView and UITableViewCell and implement my very own animation using CoreAnimation?

Implementing your own animation with CoreAnimation shouldn't be necessary when it comes to animating the rows of the table.
UITableView supports much more advanced animations than simply reloading a section and I suggest that you take a look at them.
Since you are shuffling the rows in your videos you should take a look at moveRowAtIndexPath:toIndexPath: (on UITableView). You put the calls to it within beginUpdates and endUpdates.
By knowing the order before and after the re-shuffle you can move all the rows into their new places and have them slide into their correct place.
It will take some thinking to figure out where each row should go but it will be much easier than rolling your completely custom solution.

Related

iOS : How to reload a UITableView with a lot of cells without lagging the App?

I have a lot of cells (around 3000 cells) that I need to reload constantly. I was wondering if there is currently a way to reload it faster without it lagging the App. I do the typical [tableview reloadData]; Any tips or suggestions are appreciated.
Don't implement tableView:heightForRow: in your delegate or it will slow down considerably as it recalculates every row. iOS checks to see if you implement that method and if you define it the OS changes its table height calculation from a simple multiply to a loop over the cells.
Since you have not provided context or code to show where you call [tableview reloadData];, I can only talk in generalities.
I am going to assume in your 3,000 rows possible 20 are displayed at a time.
Here is the sequence of events or actions that needs to occurs
A row gets update
Check if row is visible: indexPathForVisibleRows
If row is not visible, nothing to do
If row is visible, then following actions should be taken
[tableview beginUpdates]
[tableview reloadRowsAtIndexPaths...]
[tableview endUpdates]
Reload only visible cells if you have consistent number of items, otherwise use insert/delete methods to add cells to tableview.
When making a reloadData for your tableView, tableView:heightForRow: delegate function make a height recalculation of every row.
My solution is to save the heights for your cells already calculated (create an NSDictionary that contains all row heights. exp. create a NSDictionary with keys is the id of object that will be show on the cell and the value is the height).
When tableView attempt to recalculate the height of each cell, it will check if we have already a saved entry in your dictionary with this key (id of object), and tableView:heightForRow: will return this value if found.
I am using this solution in my chat app, and I noticed a performance increase.
Good luck.

When reloading a UITableView section, all sections flash

I'm using a UITableViewController, and am using:
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sectionNumber] withRowAnimation:UITableViewRowAnimationNone];
to reload an individual section of the tableview (to animate the insertion of new cells). The issue is that all of the sections, and their cells, flash white briefly every time this call is made. This does not occur if I use
[self.tableview reloadData];
but does occur no matter which row animation I use.
I'm aware that I can use insertRowsAtIndexPaths:withRowAnimation:, but I currently have a race condition that doesn't allow me to use that. I will, at some point, fix that, but in the meantime I would like to know why all sections cells flash while I'm reloading a single section. In addition, if I can turn off the flash and just animate the insertion / deletion of cells, that would be ideal.
I believe that it flashes because when you reload a specific section, it still has to recalculate the size of all the visible sections. Hence the flash. Without using insertion/deletion (because it knows the table will only change by one), you can't get past that.
If you are just trying this in the simulator though, it is possible that the flash will either disappear or be less noticeable when loaded on an actual device.
May be it's too late. But it could help someone.
Obj-c:
[UIView performWithoutAnimation:^{
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[indexPath section]] withRowAnimation:UITableViewRowAnimationNone];
}];
Swift 5:
UIView.performWithoutAnimation {
self.tableView.reloadSections(NSIndexSet(index: indexPath.section), with: .none)
}

How to increase number of rows in UITableview at run time?

I want to know whether there is any way to increase the number of rows of a UITableview without calling reload? I dont want to reload entire table just add new rows at run time.
i Know how to insert new row and updates but the row count increases only after calling reload on the UITableView object is there a way out?
try to do something like this:
NSIndexPath *indexPath1 = [NSIndexPath indexPathForRow:0 inSection:1];
//put these indexpaths in a NSArray
[tableView insertRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationNone];
In general, I wouldn't worry too much about calling reloadData on a table view. UITableView is actually very efficient at displaying and reusing cells.
Just make sure you're correctly creating cells (using a cell reuse identifier), or else you could be (or rather, are likely) leaking memory, and this isn't efficient (it is processor expense to constantly create new cells, instead of reusing them).
If you are new to using UITableView, or need a refresher on using them, here's a tutorial on it:
http://www.iosdevnotes.com/2011/10/uitableview-tutorial/
There's also a ton of good tutorials (you can likely just click any at random, and it will have an example somewhere within it using UITableView) on Ray Wenderlich's site:
http://www.raywenderlich.com/

Reloading UITableView data according to slider value

I'm trying to implement a table view which should display cells according to the value of a UISlider.
Example: The table is empty. The user quickly drags the slider up to a value of 400. Now the table should contain 400 rows.
The data the cells should show is stored in core data and has about 400 entries. We're trying to achieve a cool effect when dragging the slider, so you can visually see each cell being added (if you're viewing the part of the table view where the cell would end up, of course). The built in animations supplied when using - (void) reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation are sufficient, and the effect looks cool when going between 1 to 10 rows.
The problem: After the value has reached 10 or more it starts to lag too much to work. I think it's because reloadSections: has to check every cell every time the slider changes value and I loose too much precious time.
So, I'm looking for ideas on how to implement this. Should I use an NSFetchedResultsController and change the fetch request every time the slider changes value (which could happen 20 times per second)? Should I have all the data loaded into an array and just reuse cells the standard way?
I've tried both ways and the lag is pretty much the same. I'm thinking the problem might be that reloadSection: is too slow. I'm thinking that - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation would be a better choice, but I'm looking for more ideas on how to implement this.
Any help would be appreciated!
The last code I tested when the slider changes value:
- (IBAction) sliderChangedValue:(UISlider *)slider
{
// Make sure we only run this function on integer changes. It fires too often on float changes.
if ((int)slider.value == lastSliderIntegerValue) {
return;
}
if (slider.value > lastSliderIntegerValue) {
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(int)slider.value inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
else {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:(int)slider.value inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
lastSliderIntegerValue = (int)slider.value;
I'm not incredibly experienced with iOS development, but I have done a lot of game dev. It seems like the root of your problem is the amount of animation that your program has to render. Since you said that your motivation for this program is preserving the cool effect, then you should change everything possible to optimize your program up to the point the user can perceive. I understand that isn't very clear, so here's a possible solution:
You shouldn't be animating the addition of every single row for every speed at which the user can move the slider. Instead, only animate as many as you need to for the experience to be smooth. This can be accomplished by calculating the rate at which the slider is being changed, and then adjusting how many rows are added to the table before reloadData is called. Only animate the addition of the last row in the cycle.
Because I don't know what system you're developing for or really much at all about the graphical power of the various iOS platforms, I can't really give you specific values, but you should play around with different settings and see what works.

deleteRowsAtIndexPaths without animation

I got an app with a UITTableView. This table is updatable. And when in the next update the number of rows are less than in previous version, i implement the UITableView's method - deleteRowsAtIndexPaths.
I do it in this way:
[table beginUpdates];
[table deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
[table reloadRowsAtIndexPaths:indexPathsReload withRowAnimation:UITableViewRowAnimationNone];
[table endUpdates];
But when i implement this code there are animations. And this animation is really bad. A lot of black leaks. But i did write - withRowAnimation:UITableViewRowAnimationNone in both methods: delete and reload.
Why? How can i reload and delete rows without animation?
Usually the way this is done is by modifying the data source of the table, and calling reloadData on the table.
maybe you try to work with NSMutableArray (delete row by removeObjectAtIndex:indexPath.row) in TableView and reload the whole tableview by using [tableView reloadData] ?
You can try to make that "gesture" out of the table,and try reload table
Unlike what the name suggests *UITableViewRowAnimationNone* doesn't help at all.
Maybe setting the alpha on the cell works as suggested here. Not sure though.
problems with animation when deleting the last row of a TableView in ios7

Resources