Reload tableview section without scroll or animation - ios

I am reloading a tableView section using this code -
self.tableView.beginUpdates()
self.tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.None)
self.tableView.endUpdates()
Still the rows replacement is animated and the table view scrolls to the top.
How can I make sure that no animation will be applied to the section reload + prevent the table view from scrolling.

To prevent scrolling and animation, do this:
UIView.performWithoutAnimation {
let loc = tableView.contentOffset
tableView.reloadRows(at: [indexPath], with: .none)
tableView.contentOffset = loc
}

Swift 4:
Actually, the best way to prevent crazy animation during scrolling or expand/collapse cells is:
UIView.performWithoutAnimation {
self.tableView.reloadRows(at: [indexPath], with: .none)
}

Try this:
UIView.setAnimationsEnabled(false)
self.tableView.beginUpdates()
self.tableView.reloadSections(NSIndexSet(index: 1) as IndexSet, with: UITableViewRowAnimation.none)
self.tableView.endUpdates()

Swift 5
UIView.performWithoutAnimation {
self.tableView.reloadRows(at: [indexPath], with: .none)
}

Neither of given answers worked for me.
Here's the solution I found, hope it would be useful to someone
Swift 4:
let lastScrollOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.reloadSections(IndexSet(integer: 1), with: .none)
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(lastScrollOffset, animated: false)

Add one line more to this method in viewDidLoad
self.tableView.remembersLastFocusedIndexPath = true
Add this code where you want refresh after updation
UIView.setAnimationsEnabled(false)
self.tableView.beginUpdates()
self.tableView.reloadSections(NSIndexSet(index: 1) as IndexSet, with: UITableViewRowAnimation.none)
self.tableView.endUpdates()

Objective-C:
[UIView setAnimationsEnabled:NO];
[[self tableView]beginUpdates];
[self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];
[[self tableView]endUpdates];
But I think the following code is more useful and better.
[UIView performWithoutAnimation:^{
[[self tableView]beginUpdates];
[self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];
[[self tableView]endUpdates];
}];

I've had this problem too. It seems to stem from putting an IndexPath inside .reloadSections instead of a IndexSet as it requests. Which is why it seems to work with .reloadRows with out issue:
tableView.reloadRows(at: [IndexPath], with: UITableView.RowAnimation)
tableView.reloadSections(IndexSet, with: UITableView.RowAnimation)
Just wrap the section you want to reload as an IndexSet:
tableView.reloadSections(IndexSet(integer: sectionInt), with: .none)

Related

How to reload a specific cell with out animation in swift 3?

I am trying to like a post in a tableview, after getting response i need to update like status in my tableview without knowing to user that table is reloading.
let indexPath = IndexPath(item: tag, section: 0)
self.tableCommunity.reloadRows(at: [indexPath], with: .fade)
buddy try using code :-
let indexPath = IndexPath(item: tag, section: 0)
self.tableCommunity.reloadRows(at: [indexPath], with: .none)
Hope it will work.

iOS TableView delay between adding new cells

I'm working with UITableView and I want to add new items once at a time instead of adding them all at one time when there are multiple new items. Right now, my code is like this:
for rowNum in 0...(counter-1) {
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {
self.tableView.insertRows(at: [IndexPath(row: rowNum, section: lastSection)], with: .fade)
}
}
But it's not working.
It's been a while but maybe I can help. While inserting new rows or sections, you need to use tableView.beginUpdates() and tableView.endUpdates(). Also, between these two functions, row numbers and the count of the array should be equal. Otherwise an error is thrown. Try this:
let when = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: when) {
self.tableView.beginUpdates()
self.<yourArray>.append(<newElement>)
self.tableView.insertRows(at: [IndexPath(row: self.<yourArray>.count - 1,
section: lastSection)], with: .fade)
self.tableView.endUpdates()
}

How to add last row to UITableView with smooth scrolling?

I'm building chat interface using UITableView. i'm adding cells using below code
self.tableView.beginUpdates()
self.tableView.insertRows(at: [IndexPath(row: self.messageCards.count - 1, section: 0)], with: .bottom)
self.tableView.endUpdates()
and after adding i'm using scrollToRowAtIndexPath to show last inserted row.
let indexPath = IndexPath(row: self.messageCards.count - 1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
but at the end both animation are mixing and scrolling not happening smoothly.
You can try this, I have tested the code:
arrayData.addObject(str)
let indexpath = NSIndexPath(forRow: arrayData.count-1, inSection: 0)
tblView.insertRowsAtIndexPaths([indexpath], withRowAnimation: UITableViewRowAnimation.Automatic)
tblView.scrollToRowAtIndexPath(indexpath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
Following is output: let me know if you want complete source.
Please check out this.
[UITableView animateWithDuration:5.0 delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:self.messageCards.count-1 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
} completion:^(BOOL finished) {
NSLog(#"animated");
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathWithIndex:self.messageCards.count-1] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}];
Its wonder, but to achieve smooth adding when scrolling just need to call reloadData()
func fetchNext(_ countToFetch: Int? = 10) {
let existingCount = items?.count ?? 0
networkService?.items(bySkip: existingCount, take: countToFetch, completion: { (data, error) in
if let newItems = data?.items() as? [Element], newItems.count > 0 {
self.items?.append(contentsOf: newItems)
self.refreshCallback?()
}
})
}
Callback is:
datasource?.refreshCallback = { [weak self] in
if #available(iOS 10.0, *) {
self?.table.refreshControl?.endRefreshing()
}
self?.table.reloadData()
}
[self.messageCards addObject:#"DATA Whatever you want"];
[self.tableView reloadData];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messageCards.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];

Random scrolling while reloading uitableviewcell, iOs/Swift

I am developing news feed and I am using uitableview to display data. I am loading each cell data synchronically in other thread and use protocol method to display loaded data:
func nodeLoaded(node: NSMutableDictionary) {
for var i = 0; i < nodesArray.count; ++i {
if ((nodesArray[i]["id"] as! Int) == (node["id"] as! Int)) {
nodesArray[i] = node
CATransaction.setDisableActions(true)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
CATransaction.setDisableActions(false)
}
}
}
The problem is that when I scrolling down (while tableview updating), tableview push me on the top. I was searching answer on this problem, but nothing helps me. I already tried to disable animation:
CATransaction.setDisableActions(true)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
CATransaction.setDisableActions(false)
2)
UIView.setAnimationsEnabled(false)
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
UIView.setAnimationsEnabled(true)
But the story always the same.
I have the desired effect when I simply don't use self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
, but in this case data reload only if I scroll down and then return back to cell.
Maybe the problem is that I use auto layout and tableview recalculate its height every time? But I don't know how to fix it
You can build the reload mechanism yourself.
Iterate over all visible cells (tableView.visibleCells) and apply the same logic to them as you would in -tableView:cellForRowAtIndexPath:.
If you need the index path to perform this update, you can ask the table view for it (-indexPathForCell:).

UITableView add cell Animation

Can any one help me out with UITableView animating issue?
By default we have animation for deleting cell and reordering cells in UITableView.
Can we have animated adding cell, if so how to do it.
I have checked out Three20, did not not get how twitter has done the table expand animation under MyProfile>ReTweets.
Want to try it without Three20 frameowrk, using the existing animation in UITableView.
You can use the following UITableView method:
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
Example with self.dataSource being a mutable array and your table only having 1 section:
[self.dataSource addObject:#"New Item"];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:[self.dataSource count]-1 inSection:0];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
Note: Subtracted 1 from datasource count since NSIndexPath is zero indexed.
Swift
Example array that is the data source for the table view
var myArray = ["Cow", "Camel", "Sheep", "Goat"]
The following will add a row with animation at the top of the table view.
// add item to current array
myArray.insert("Horse", atIndex: 0)
// insert row in table
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
Multiple updates
If you need to do multiple insertions and/or deletions then surround them with beginUpdates() and endUpdates().
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths([addIndexPath1, addIndexPath2, ...], withRowAnimation: .Fade)
tableView.deleteRowsAtIndexPaths([deleteIndexPath1, deleteIndexPath2, ...], withRowAnimation: .Fade)
tableView.endUpdates()
Further reading
Documentation
Use reloadRowsAtIndexPaths:indexPath
tableView.beginUpdates()
[tableView reloadRowsAtIndexPaths:indexPath withRowAnimation:UITableViewRowAnimationAutomatic];
tableView.endUpdates()
i hope this will help you..
In swift is also possible using:
func insertRow(entries: [String]) {
tableView.performBatchUpdates({
self.tableView.insertRows(at: [IndexPath(row: entries.count - 1, section: 0)], with: .bottom)
}, completion: nil)
}

Resources