I have a UITableView that has two modes. When we switch between the modes I have a different number of sections and cells per section. Ideally, it would do some cool animation when the table grows or shrinks.
Here is the code I tried, but it doesn't do anything:
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.5];
[self.tableView reloadData];
[UIView commitAnimations];
Any thoughts on how I could do this?
This question is related to
cocoa-touch
animation
The way to approach this is to tell the tableView to remove and add rows and sections with the
insertRowsAtIndexPaths:withRowAnimation:
,
deleteRowsAtIndexPaths:withRowAnimation:
,
insertSections:withRowAnimation:
and
deleteSections:withRowAnimation:
methods of UITableView.
When you call these methods, the table will animate in/out the items you requested, then call reloadData on itself so you can update the state after this animation. This part is important - if you animate away everything but don't change the data returned by the table's dataSource, the rows will appear again after the animation completes.
So, your application flow would be:
[self setTableIsInSecondState:YES];
[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];
As long as your table's dataSource methods return the correct new set of sections and rows by checking [self tableIsInSecondState]
(or whatever), this will achieve the effect you're looking for.
If you want to add your own custom animations to UITableView cells, use
[theTableView reloadData];
[theTableView layoutSubviews];
NSArray* visibleViews = [theTableView visibleCells];
to get an array of visible cells. Then add any custom animation to each cell.
Check out this gist I posted for a smooth custom cell animation. https://gist.github.com/floprr/1b7a58e4a18449d962bd
I can't comment on the top answer, but a swift implementation would be:
self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade)
you could include as many sections as you want to update in the first argument for reloadSections.
Other animations available from the docs: https://developer.apple.com/reference/uikit/uitableviewrowanimation
fade The inserted or deleted row or rows fade into or out of the table view.
right The inserted row or rows slide in from the right; the deleted row or rows slide out to the right.
left The inserted row or rows slide in from the left; the deleted row or rows slide out to the left.
top The inserted row or rows slide in from the top; the deleted row or rows slide out toward the top.
bottom The inserted row or rows slide in from the bottom; the deleted row or rows slide out toward the bottom.
case none The inserted or deleted rows use the default animations.
middle The table view attempts to keep the old and new cells centered in the space they did or will occupy. Available in iPhone 3.2.
automatic The table view chooses an appropriate animation style for you. (Introduced in iOS 5.0.)
For Swift 4
tableView.reloadSections([0], with: UITableView.RowAnimation.fade)
All of these answers assume that you are using a UITableView with only 1 section.
To accurately handle situations where you have more than 1 section use:
NSRange range = NSMakeRange(0, myTableView.numberOfSections);
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
[myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
(Note: you should make sure that you have more than 0 sections!)
Another thing to note is that you may run into a NSInternalInconsistencyException if you attempt to simultaneously update your data source with this code. If this is the case, you can use logic similar to this:
int sectionNumber = 0; //Note that your section may be different
int nextIndex = [currentItems count]; //starting index of newly added items
[myTableView beginUpdates];
for (NSObject *item in itemsToAdd) {
//Add the item to the data source
[currentItems addObject:item];
//Add the item to the table view
NSIndexPath *path = [NSIndexPath indexPathForRow:nextIndex++ inSection:sectionNumber];
[myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[myTableView endUpdates];
Native UITableView
animations in Swift
Insert and delete rows all at once with tableView.performBatchUpdates
so they occur simultaneously. Building on the answer from @iKenndac use methods such as:
tableView.insertSections
tableView.insertRows
tableView.deleteSections
tableView.deleteRows
Ex:
tableView.performBatchUpdates({
tableView.insertSections([0], with: .top)
})
This inserts a section at the zero position with an animation that loads from the top. This will re-run the cellForRowAt
method and check for a new cell at that position. You could reload the entire table view this way with specific animations.
Re: the OP question, a conditional flag would have been needed to show the cells for the alternate table view state.
I can't comment on the top answer, but a swift implementation would be:
self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade)
you could include as many sections as you want to update in the first argument for reloadSections.
Other animations available from the docs: https://developer.apple.com/reference/uikit/uitableviewrowanimation
fade The inserted or deleted row or rows fade into or out of the table view.
right The inserted row or rows slide in from the right; the deleted row or rows slide out to the right.
left The inserted row or rows slide in from the left; the deleted row or rows slide out to the left.
top The inserted row or rows slide in from the top; the deleted row or rows slide out toward the top.
bottom The inserted row or rows slide in from the bottom; the deleted row or rows slide out toward the bottom.
case none The inserted or deleted rows use the default animations.
middle The table view attempts to keep the old and new cells centered in the space they did or will occupy. Available in iPhone 3.2.
automatic The table view chooses an appropriate animation style for you. (Introduced in iOS 5.0.)
I believe you can just update your data structure, then:
[tableView beginUpdates];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView endUpdates];
Also, the "withRowAnimation" is not exactly a boolean, but an animation style:
UITableViewRowAnimationFade,
UITableViewRowAnimationRight,
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,
UITableViewRowAnimationMiddle
CATransition
class.(don't forget to import QuartzCore
)
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.fillMode = kCAFillModeForwards;
transition.duration = 0.5;
transition.subtype = kCATransitionFromBottom;
[[self.tableView layer] addAnimation:transition forKey:@"UITableViewReloadDataAnimationKey"];
Change the type
to match your needs, like kCATransitionFade
etc.
let transition = CATransition()
transition.type = kCATransitionPush
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.fillMode = kCAFillModeForwards
transition.duration = 0.5
transition.subtype = kCATransitionFromTop
self.tableView.layer.addAnimation(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()
Reference for CATransition
let transition = CATransition()
transition.type = CATransitionType.push
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.fillMode = CAMediaTimingFillMode.forwards
transition.duration = 0.5
transition.subtype = CATransitionSubtype.fromTop
self.tableView.layer.add(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()
Animating without reloadData() in Swift can be done like this (as of version 2.2):
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove ?? 0
// Do your work here
while numOfCellsToRemove > 0 {
// ...or here, if you need to add/remove the same amount of objects to/from somewhere
indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
in case you need to call reloadData() after the animation ends, you can embrace the changes in CATransaction like this:
CATransaction.begin()
CATransaction.setCompletionBlock({() in self.tableview.reloadData() })
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove.count ?? 0
// Do your work here
while numOfCellsToRemove > 0 {
// ...or here, if you need to add/remove the same amount of objects to/from somewhere
indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
CATransaction.commit()
The logic is shown for the case when you delete rows, but the same idea works also for adding rows. You can also change animation to UITableViewRowAnimation.Left to make it neat, or choose from the list of other available animations.
UITableView has a field called 'indexPathsForVisibleRows' that you can use to animate the visible rows using the 'reloadItemsAtIndexPaths' method.
guard let indexPaths = tableView.indexPathsForVisibleRows
else { return }
self.tableView.layoutIfNeeded()
self.tableView.reloadItemsAtIndexPaths(indexPaths, animationStyle: .automatic)
Swift Implementation:
let range = NSMakeRange(0, self.tableView!.numberOfSections())
let indexSet = NSIndexSet(indexesInRange: range)
self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)
The way to approach this is to tell the tableView to remove and add rows and sections with the
insertRowsAtIndexPaths:withRowAnimation:
,
deleteRowsAtIndexPaths:withRowAnimation:
,
insertSections:withRowAnimation:
and
deleteSections:withRowAnimation:
methods of UITableView.
When you call these methods, the table will animate in/out the items you requested, then call reloadData on itself so you can update the state after this animation. This part is important - if you animate away everything but don't change the data returned by the table's dataSource, the rows will appear again after the animation completes.
So, your application flow would be:
[self setTableIsInSecondState:YES];
[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];
As long as your table's dataSource methods return the correct new set of sections and rows by checking [self tableIsInSecondState]
(or whatever), this will achieve the effect you're looking for.
I believe you can just update your data structure, then:
[tableView beginUpdates];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[tableView endUpdates];
Also, the "withRowAnimation" is not exactly a boolean, but an animation style:
UITableViewRowAnimationFade,
UITableViewRowAnimationRight,
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone,
UITableViewRowAnimationMiddle
CATransition *animation = [CATransition animation];
animation.duration = .3;
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setDuration:.3];
[[_elementTableView layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"];
[tableView reloadData];
The way to approach this is to tell the tableView to remove and add rows and sections with the
insertRowsAtIndexPaths:withRowAnimation:
,
deleteRowsAtIndexPaths:withRowAnimation:
,
insertSections:withRowAnimation:
and
deleteSections:withRowAnimation:
methods of UITableView.
When you call these methods, the table will animate in/out the items you requested, then call reloadData on itself so you can update the state after this animation. This part is important - if you animate away everything but don't change the data returned by the table's dataSource, the rows will appear again after the animation completes.
So, your application flow would be:
[self setTableIsInSecondState:YES];
[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];
As long as your table's dataSource methods return the correct new set of sections and rows by checking [self tableIsInSecondState]
(or whatever), this will achieve the effect you're looking for.
Animating without reloadData() in Swift can be done like this (as of version 2.2):
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove ?? 0
// Do your work here
while numOfCellsToRemove > 0 {
// ...or here, if you need to add/remove the same amount of objects to/from somewhere
indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
in case you need to call reloadData() after the animation ends, you can embrace the changes in CATransaction like this:
CATransaction.begin()
CATransaction.setCompletionBlock({() in self.tableview.reloadData() })
tableview.beginUpdates()
var indexPathsToDeleteForAnimation: [NSIndexPath] = []
var numOfCellsToRemove = ArrayOfItemsToRemove.count ?? 0
// Do your work here
while numOfCellsToRemove > 0 {
// ...or here, if you need to add/remove the same amount of objects to/from somewhere
indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0))
numOfCellsToRemove -= 1
}
tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right)
tableview.endUpdates()
CATransaction.commit()
The logic is shown for the case when you delete rows, but the same idea works also for adding rows. You can also change animation to UITableViewRowAnimation.Left to make it neat, or choose from the list of other available animations.
Swift 4 version for @dmarnel answer:
tableView.reloadSections(IndexSet(integer: 0), with: .automatic)
All of these answers assume that you are using a UITableView with only 1 section.
To accurately handle situations where you have more than 1 section use:
NSRange range = NSMakeRange(0, myTableView.numberOfSections);
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
[myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
(Note: you should make sure that you have more than 0 sections!)
Another thing to note is that you may run into a NSInternalInconsistencyException if you attempt to simultaneously update your data source with this code. If this is the case, you can use logic similar to this:
int sectionNumber = 0; //Note that your section may be different
int nextIndex = [currentItems count]; //starting index of newly added items
[myTableView beginUpdates];
for (NSObject *item in itemsToAdd) {
//Add the item to the data source
[currentItems addObject:item];
//Add the item to the table view
NSIndexPath *path = [NSIndexPath indexPathForRow:nextIndex++ inSection:sectionNumber];
[myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[myTableView endUpdates];
Actually, it's very simple:
[_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
From the documentation:
Calling this method causes the table view to ask its data source for new cells for the specified sections. The table view animates the insertion of new cells in as it animates the old cells out.
You might want to use:
Objective-C
[UIView transitionWithView: self.tableView
duration: 0.35f
options: UIViewAnimationOptionTransitionCrossDissolve
animations: ^(void)
{
[self.tableView reloadData];
}
completion: nil];
Swift
UIView.transitionWithView(tableView,
duration: 0.35,
options: .TransitionCrossDissolve,
animations:
{ () -> Void in
self.tableView.reloadData()
},
completion: nil);
Swift 3, 4 & 5
UIView.transition(with: tableView,
duration: 0.35,
options: .transitionCrossDissolve,
animations: { self.tableView.reloadData() }) // left out the unnecessary syntax in the completion block and the optional completion parameter
No hassles. :D
You can also use any of the UIViewAnimationOptionTransitions
you want for cooler effects:
transitionNone
transitionFlipFromLeft
transitionFlipFromRight
transitionCurlUp
transitionCurlDown
transitionCrossDissolve
transitionFlipFromTop
transitionFlipFromBottom
For Swift 4
tableView.reloadSections([0], with: UITableView.RowAnimation.fade)
UITableView has a field called 'indexPathsForVisibleRows' that you can use to animate the visible rows using the 'reloadItemsAtIndexPaths' method.
guard let indexPaths = tableView.indexPathsForVisibleRows
else { return }
self.tableView.layoutIfNeeded()
self.tableView.reloadItemsAtIndexPaths(indexPaths, animationStyle: .automatic)
To reload all sections, not just one with custom duration.
User duration
parameter of UIView.animate
to set custom duration.
UIView.animate(withDuration: 0.4, animations: { [weak self] in
guard let `self` = self else { return }
let indexSet = IndexSet(integersIn: 0..<self.tableView.numberOfSections)
self.tableView.reloadSections(indexSet, with: UITableView.RowAnimation.fade)
})
In my case, I wanted to add 10 more rows into the tableview (for a "show more results" type of functionality) and I did the following:
NSInteger tempNumber = self.numberOfRows;
self.numberOfRows += 10;
NSMutableArray *arrayOfIndexPaths = [[NSMutableArray alloc] init];
for (NSInteger i = tempNumber; i < self.numberOfRows; i++) {
[arrayOfIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
In most cases, instead of "self.numberOfRows", you would usually use the count of the array of objects for the tableview. So to make sure this solution works well for you, "arrayOfIndexPaths" needs to be an accurate array of the index paths of the rows being inserted. If the row exists for any of this index paths, the code might crash, so you should use the method "reloadRowsAtIndexPaths:withRowAnimation:" for those index pathds to avoid crashing
If you want to add your own custom animations to UITableView cells, use
[theTableView reloadData];
[theTableView layoutSubviews];
NSArray* visibleViews = [theTableView visibleCells];
to get an array of visible cells. Then add any custom animation to each cell.
Check out this gist I posted for a smooth custom cell animation. https://gist.github.com/floprr/1b7a58e4a18449d962bd
You might want to use:
Objective-C
[UIView transitionWithView: self.tableView
duration: 0.35f
options: UIViewAnimationOptionTransitionCrossDissolve
animations: ^(void)
{
[self.tableView reloadData];
}
completion: nil];
Swift
UIView.transitionWithView(tableView,
duration: 0.35,
options: .TransitionCrossDissolve,
animations:
{ () -> Void in
self.tableView.reloadData()
},
completion: nil);
Swift 3, 4 & 5
UIView.transition(with: tableView,
duration: 0.35,
options: .transitionCrossDissolve,
animations: { self.tableView.reloadData() }) // left out the unnecessary syntax in the completion block and the optional completion parameter
No hassles. :D
You can also use any of the UIViewAnimationOptionTransitions
you want for cooler effects:
transitionNone
transitionFlipFromLeft
transitionFlipFromRight
transitionCurlUp
transitionCurlDown
transitionCrossDissolve
transitionFlipFromTop
transitionFlipFromBottom
Actually, it's very simple:
[_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
From the documentation:
Calling this method causes the table view to ask its data source for new cells for the specified sections. The table view animates the insertion of new cells in as it animates the old cells out.
Swift Implementation:
let range = NSMakeRange(0, self.tableView!.numberOfSections())
let indexSet = NSIndexSet(indexesInRange: range)
self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic)
In my case, I wanted to add 10 more rows into the tableview (for a "show more results" type of functionality) and I did the following:
NSInteger tempNumber = self.numberOfRows;
self.numberOfRows += 10;
NSMutableArray *arrayOfIndexPaths = [[NSMutableArray alloc] init];
for (NSInteger i = tempNumber; i < self.numberOfRows; i++) {
[arrayOfIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
In most cases, instead of "self.numberOfRows", you would usually use the count of the array of objects for the tableview. So to make sure this solution works well for you, "arrayOfIndexPaths" needs to be an accurate array of the index paths of the rows being inserted. If the row exists for any of this index paths, the code might crash, so you should use the method "reloadRowsAtIndexPaths:withRowAnimation:" for those index pathds to avoid crashing
The way to approach this is to tell the tableView to remove and add rows and sections with the
insertRowsAtIndexPaths:withRowAnimation:
,
deleteRowsAtIndexPaths:withRowAnimation:
,
insertSections:withRowAnimation:
and
deleteSections:withRowAnimation:
methods of UITableView.
When you call these methods, the table will animate in/out the items you requested, then call reloadData on itself so you can update the state after this animation. This part is important - if you animate away everything but don't change the data returned by the table's dataSource, the rows will appear again after the animation completes.
So, your application flow would be:
[self setTableIsInSecondState:YES];
[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];
As long as your table's dataSource methods return the correct new set of sections and rows by checking [self tableIsInSecondState]
(or whatever), this will achieve the effect you're looking for.
Swift 4 version for @dmarnel answer:
tableView.reloadSections(IndexSet(integer: 0), with: .automatic)
CATransition
class.(don't forget to import QuartzCore
)
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.fillMode = kCAFillModeForwards;
transition.duration = 0.5;
transition.subtype = kCATransitionFromBottom;
[[self.tableView layer] addAnimation:transition forKey:@"UITableViewReloadDataAnimationKey"];
Change the type
to match your needs, like kCATransitionFade
etc.
let transition = CATransition()
transition.type = kCATransitionPush
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.fillMode = kCAFillModeForwards
transition.duration = 0.5
transition.subtype = kCATransitionFromTop
self.tableView.layer.addAnimation(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()
Reference for CATransition
let transition = CATransition()
transition.type = CATransitionType.push
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.fillMode = CAMediaTimingFillMode.forwards
transition.duration = 0.5
transition.subtype = CATransitionSubtype.fromTop
self.tableView.layer.add(transition, forKey: "UITableViewReloadDataAnimationKey")
// Update your data source here
self.tableView.reloadData()
Native UITableView
animations in Swift
Insert and delete rows all at once with tableView.performBatchUpdates
so they occur simultaneously. Building on the answer from @iKenndac use methods such as:
tableView.insertSections
tableView.insertRows
tableView.deleteSections
tableView.deleteRows
Ex:
tableView.performBatchUpdates({
tableView.insertSections([0], with: .top)
})
This inserts a section at the zero position with an animation that loads from the top. This will re-run the cellForRowAt
method and check for a new cell at that position. You could reload the entire table view this way with specific animations.
Re: the OP question, a conditional flag would have been needed to show the cells for the alternate table view state.
To reload all sections, not just one with custom duration.
User duration
parameter of UIView.animate
to set custom duration.
UIView.animate(withDuration: 0.4, animations: { [weak self] in
guard let `self` = self else { return }
let indexSet = IndexSet(integersIn: 0..<self.tableView.numberOfSections)
self.tableView.reloadSections(indexSet, with: UITableView.RowAnimation.fade)
})
CATransition *animation = [CATransition animation];
animation.duration = .3;
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setDuration:.3];
[[_elementTableView layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"];
[tableView reloadData];
Source: Stackoverflow.com