I have a UITableView. I want to add a cell to the beginning of the tableView with animation. I tried the following:
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
tableView.reloadRowsAtIndexPaths(indexPath, withRowAnimation: UITableViewRowAnimation.Automatic)
But I get the following error:
Cannot invoke 'reloadRowsAtIndexPaths' with an argument list of type
'(NSIndexPath!, withRowAnimation: UITableViewRowAnimation)'
(When I just do tableView.reloadData() it works fine.)
What am I doing wrong, and how can I fix it?
tableView.reloadRowsAtIndexPaths expects an [NSIndexPath] instead of an NSIndexPath! as first argument.
so fix it by calling
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
let indexPaths = [indexPath]
tableView.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.Automatic)
You get the error, because reloadRowsAtIndexPaths expects an array of index paths, not a single index path. However reloadRowsAtIndexPaths wouldn't add a cell, but just reload the cells at the specified index paths.
Instead you should use insertRowsAtIndexPaths to add your cell.
Related
I am loading an array to UIcollectionview(later will add other data) . I want to select collection view item randomly as:
var indexpath = Int(arc4random_uniform(UInt32(items.count)-1)
self.collectionview.selectitem(at: **indexpath**, animated:true ,scrollPosition:UICollectionViewScrollPosition)
Here it’s giving me error at bold position saying:
cannot convert value of type Int to expected argument type 'IndexPath?
I can understand this exception as indexpath is different in swift from collection data index(array index). But I am unable to find any method that can convert item index to indexpath or anyother way.
I am newer to iOS so might be not good at searching correct keywords for such issue. It will be a great favour from you all for any other method to this requirement.
To create an IndexPath in swift 3 for UICollectionView
let indexPath = IndexPath(item: 0, section: 0)
You can use it
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
Swift 3 Latest
self.table.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .fade)
Swift 4.1. Here I created function to get NSIndexPath. Just pass your UIView(UIButton,UITextField etc) and UICollectionView object to get NSIndexPath.
func getIndexPathFor(view: UIView, collectionView: UICollectionView) -> NSIndexPath? {
let point = collectionView.convert(view.bounds.origin, from: view)
let indexPath = collectionView.indexPathForItem(at: point)
return indexPath as NSIndexPath?
}
I want to update a particular UITableViewCell into the Swift IOS.
"reloadRowsAtIndexPaths" is used for updating the particular UITableViewCell,
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
My Concern is "How to get the IndexPath.row and IndexPath.section" ([indexPath] for this Case ) before creating the UITableView , i want to pass both to update the particular UItableViewCell.
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .None)
With this you can init a NSIndexPath variable. [] brackets because reloadRowsAtIndexPath wants an array of those as parameter.
Parameters in NSIndexPath initializer are pretty straight forward i guess (forRow --> which row | inSection --> which section
hf ;)
My TableView is doing some kind of auto-scrolling after any kind of updates are applied to it. If I were to append a new element to the array that contains the items which are presented in the UITableView, for some reason my Table View scrolls up somewhat randomly up around 50% up the middle of the contents of the TableView.
Here's the function that deals with updating, not inserting an item into the Table View:
func updateLastMessage() {
var section = msgSections.count - 1
var row = msgSections[section].msg.count - 1
let indexPath = NSIndexPath(forRow: row, inSection: section)
self.tableView.beginUpdates()
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
self.tableView.endUpdates()
}
This function above works perfectly, but after I call reloadRowsAtIndexPaths on self.tableView, the table view automatically scrolls up 50% of the contents of the Table View. I get exactly the same result if I were to insert an item instead:
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
self.tableView.endUpdates()
Also, if I were to comment out both beginUpdates() and endUpdates(), there seems to be no effect to the scrolling.
I only know of one hack to somewhat get around this issue by using setContentOffset to return the scroll position back to where it was before a message was updated, or a new message is inserted:
func updateLastMessage() {
let currentContentOffset = self.tableView.contentOffset
var section = msgSections.count - 1
var row = msgSections[section].msg.count - 1
let indexPath = NSIndexPath(forRow: row, inSection: section)
self.tableView.beginUpdates()
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
self.tableView.endUpdates()
self.tableView.setContentOffset(currentContentOffset, animated: false)
}
This hack doesn't work in my favor, because it scrolls slowly to the top and then jolts back to where it was which looks kind of bad.
Does anyone know exactly what could be the mechanism that's causing the TableView to scroll up so much after any appended item or updated item??
It seems to work perfectly and the animation looks very nice as but only when there aren't any items in the table view.
Never call reloadRowsAtIndexPaths: withRowAnimation: inside beginUpdates() and endUpdates().
The tableView will automatically call the necessary reloading of rows at the end of endUpdates().
Just call beginUpdates() and endUpdates() without any code inside. It'll work.
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:).
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)
}