how to update a uitableview cell without reloadRows and reloadData swift - ios

I need to update tableview cell without reloadRows and reloadData method in swift. Is It possible?

You can use tableview.indexPathsForVisibleRows if you wanna just update the ones on the screen and the others will be updated through cellForRow / willDisplayCell
Then you would traditionally do something like
tableview.indexPathsForVisibleRows.forEach {
if let cell = tableview.cellForRow(at: $0) as? MyCell {
cell.configure()
}
}

Try this piece of code:
UIView.setAnimationsEnabled(false)
self.yourTableView.beginUpdates()
self.yourTableView.reloadSections(NSIndexSet(index:indexToBeReload) as IndexSet, with: UITableViewRowAnimation.none)
self.yourTableView.endUpdates()

If You want to update cell content size, You should use beginUpdates() and endUpdates() to change content size of UITableViewCell, in this case heightForRowAtindexPath will called for each cell in tableView and update height of TableviewCell. for iOS > 10, You should prefer performBatchUpdates(_:completion:) instead of beginUpdates() and endUpdates().
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.beginUpdates()
self.tableView.endUpdates()
}
For more information
https://appengineer.in/2018/07/11/resize-uitableviewcell-size-without-fluctuation-and-jerk/
https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates

Related

How to create dynamic collection view in a table view cell, without reloading table view swift?

I'm using this code in cellForRowAt :
cell.frame = tableView.bounds
cell.layoutIfNeeded()
collectionView.reloadData()
heightConstraint.constant = collectionView.collectionViewLayout.collectionViewContentSize.height
and
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
This works at the first time, but when I load more items to collection view it doesn't work unless I use tableView.reloadData()
But when I use tableView.reloadData() scrolling stops for a second, and I want it to flow without freezing.
Anyone has a solution? Thanks in advance.
You can reload only the cell that you are updating in case you don't want to reload the table
tableView.reloadRows(at: [IndexPath], with: .none)
Any time you change a cell height after it has been displayed, you need to tell the table view about it.
You haven't shown how or when you "load more items to collection view" ... but after you do that, call:
tableView.performBatchUpdates(nil, completion: nil)
That will cause the table view to recalculate and update the row heights, without calling .reloadData().

UIPickerView inside static UITableViewCell animation on cell height update issue

I have a static UITableView in which I have a UIPickerView inside a UITableViewCell. When triggering didSelectRowAt it is supposed to toggle the height of the cell that has the UIPickerView. I use beginUpdates() and endUpdates() to change the height of the cell. It looks right when expanding but when collapsing, the UIPickerView doesn't animate and collapses faster than the cell does. Not sure what I am doing wrong.
I have made sure all views are set to true for clipToBounds on the UITableViewCell, ContentView (of the UITableViewCell) and UIPickerView. I have tried to wrap the beginUpdates/endUpdates in a DispatchQueue.main.async. My UIPickerView is using AutoLayout and (leading, trailing, top, bottom) edges are equal to Content View of the cell. I am using a StoryBoard for my UI.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch (indexPath.section, indexPath.row) {
case (1,1):
showPicker = !showPicker
tableView.beginUpdates()
tableView.endUpdates()
default:
()
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch (indexPath.section, indexPath.row) {
case (1, 1):
if !showDueDate {
return 0
}
case (1, 2):
if !showPicker {
return 0
}
case (_, _):
break
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
I expected the animation to be smooth and UIPickerView to collapse alongside the UITabeViewCell.
see gif to see issue via GIPHY
Use self.tableView.reloadRows(at: IndexPath(row: indexPath.row, section: indexPath.section), with: .fade) instead of beginUpdates/endUpdates. It will give you a smooth animation when animating table changes.
Figured it out. My bottom constraint of the UIPickerView was set to the bottom of the content view, constant was 0. Changed it to <= 0 and it fixed it. Don't understand why 0 didn't work. Atleast I figured it out...

iOS UITableView deleted cell contents re appear when inserting new cell

I've a table view where cells can be inserted and deleted. For insertion of cells, I use the following code:
tableView.beginUpdates()
tableView.insertRows(at: [IndexPath(row: cellCount-2, section: 0)], with: .automatic)
tableView.endUpdates()
For deleting cells, I use the following code:
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
Attaching the gif of the issue I face. On deleting a cell and inserting a new one, the contents of the cell gets populated in the new cell. Can someone help me sort this issue?
If you are using the standard UITableViewCell remember to reset the content inside the UITableViewDelegate function cellForRowAtIndexPath since the dequeueReusableCell will recycle an already initialized cell (that has to be brought to its original state)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "aCellIdentifier", for: indexPath)!
...
cell.title.text = ""
cell.description.text = ""
}
A typical approach is however to subclass UITableViewCell and implement prepareForReuse method (which is called automatically before the cell being reused), where you will eventually reset all labels, images, subviews to the initial state
override func prepareForReuse() {
super.prepareForReuse()
self.labelScore.text = ""
self.labelDate.text = ""
}

iOS 11 UITableViewCell above viewForHeaderInSection view after deleting

I have simple UITableViewController.
View for header. Which inits from xib.
And single type of cell.
After deleting cell with swipe, cell which above deleted one become visible above HeaderView, when other cells just hides below HeaderView as it should be.
If something above not clear - ask.
Video: https://youtu.be/aX-iPnM3q4Q
I think this should solve it:
tableView.sendSubview(toFront: tableView.headerView(forSection: 0)!)
(assuming you have only 1 section)
You can set this after deleting the cell, for example in commitEditingStyle.
Found the solution.
func deleteItem(from indexPath: IndexPath, tableView: UITableView) {
cellsData.remove(at: indexPath.row)
CATransaction.begin()
tableView.beginUpdates()
CATransaction.setCompletionBlock {
tableView.reloadData()
}
tableView.deleteRows(at: [indexPath], with: .left)
tableView.endUpdates()
CATransaction.commit()
}
tableView.reloadData() do the thing that fixing appearing cell above the headerView, but kills animation. So if you don't care about animation you can add only reloadData().

how to reload a collectionview that is inside a tableviewcell

I have a collectionView inside a tableViewCell
for example:
credit: How to use StoryBoard quick build a collectionView inside UITableViewCell
I would like to reload the collectionView when I update information.
I have put a print in the collectionView's cellForItemAtIndexPath to test if it is being called but it isn't. How can I get the collectionView to reload?
I found out how! In my tableViewCell class I just need to link the collectionView as an outlet so in my tableViewCell's cellForRowAtIndexPath I just needed to call cell.collectionView.reloadData()
Simplest Way
for cell in tableView.visibleCells {
(cell as? YourTableViewCell)?.collectionView.reloadData()
}
Or
If you need to reload Specific UICollectionView
if let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? YourTableViewCell {
cell.collectionView.reloadData()
}
1st on tableview cell create this function:
func collectionReloadData(){
DispatchQueue.main.async(execute: {
self.collectionView.reloadData()
})
}
then call it from
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { ...
cell.collectionReloadData()
create tags for collection view with indexPath.row of UITableView and create an instance of the UICollectionView using the tag and reload !

Resources