Reputation: 725
I have a tableview that has fade in animation for each cell when it gets displayed. When scrolling down, my more data gets appended to my datasource and reloads my tableview. When that happens, all my tableview cells flickers(cell that is already done animating the fade in animation does the animation again). Is there a way to prevent my cells from animating again when I reload my tableview?
//reloading datasouce
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//configure cell
//check to see if reloading datasource is required
self.dataSource += additionalDataArray
self.tableView.reloadData()
return cell
}
//animating cell
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let view = cell.contentView
view.layer.opacity = 0.1
UIView.animateWithDuration(0.5, delay: 0, options: [.AllowUserInteraction, .CurveLinear], animations: { () -> Void in
view.layer.opacity = 1
}, completion: nil)
}
Upvotes: 1
Views: 1167
Reputation: 1137
Never call reloadData() inside cellForRowAtIndexPath. This method is called just before every row is displayed for every single row. When reload data is called, each row is reloaded, and cellForRowAtIndexPath is called over again for each of the displayed rows. Calling reloadData() here is causing a cycle reloading each row over and over again. A symptom of this is the flickering you are seeing. Don't call reload data in either of those delegate methods. Another set of methods needs to monitor the data source and determine when to update or not. Only update when you have updated the data.
I can see you are trying to update the data when it gets to the bottom. I don't know what problem you are trying to overcome with this solution but keep two things in mind. One is dequeueReusableCellWithIdentifier solves memory problems with tables that have large amounts of data. If you have a table that has 100 rows however only 3 are visible at a time, the tableview only allocates memory for 3 rows and reuses them over and over. Thats why cellForRowAtIndexPath is called over and over again even for rows that it already created. Its reusing a row that went off screen and laying it out again with new data. Second is Swift uses pointers to reduce allocating memory the objects that already exist. If you have all 100 data objects allocated in an array somewhere then handing all 100 to a separate array that the view controller owns won't double the memory being used. It's ok to do that.
In the case where you don't have the next 5 avaialble because you need to make another network call then you will need a method in willDisplayCell to determine when you are nearing the bottom. You will need a loading cell to indicate to the user to wait while more rows are being fetched. When you get near the loading cell the check inside willDisplayCell tell the data source to get more data. When the data is returned you reload the table. Never reload inside of cellForRowAtIndexPath. Good luck!!
Upvotes: 2