Cell does not get deselected while scrolled back - swift

I have a weird problem. While I select a cell with changing the background color of one UIView component, then I scroll down and selected cell going to be out of bounds of the view. I do select new cell -> previous one should get unselected, but it does not. Because when I back I do have 2 selected cells.
var lastSelectedAtIndexPath: IndexPath?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch tableView {
case myTableView:
if let cell = myTableView.cellForRow(at: indexPath) as? MyTableViewCell {
cell.checkMarkBorder.backgroundColor = UIColor.darkGreyFts
lastSelectedFuelAtIndexPath = indexPath
}
default:
break
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
switch tableView {
case myTableView:
if let cell = fuelTableView.cellForRow(at: indexPath) as? MyTableViewCell {
cell.checkMarkBorder.backgroundColor = UIColor.white
}
default:
break
}
}
And iside cellForRowAt I have :
let cell = myTableView.dequeueReusableCell(withIdentifier: "myCell") as! MyTableViewCell
if let lastIndexPath = lastSelectedFuelAtIndexPath {
myTableView.deselectRow(at: lastIndexPath, animated: true)
}
cell.myImage.image = UIImage(named: fuelType)?.withRenderingMode(.alwaysTemplate)
cell.myNameLabel.text = "Test"
Any ideas what is going on?
Thanks in advance!

Don't make changes on cell outside cellForRowAt always change your dataSource and use dataSource in cellForRowAt then in didSelectRowAt and didDeSelectRowAt reload the row.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier: "myCell") as! MyTableViewCell
cell.myImage.image = UIImage(named: fuelType)?.withRenderingMode(.alwaysTemplate)
cell.myNameLabel.text = "Test"
cell.checkMarkBorder.backgroundColor = lastSelectedFuelAtIndexPath == indexPath ? UIColor.darkGreyFts : UIColor.white
return cell
}
Now in didSelectRowAt and didDeSelectRowAt update the lastSelectedFuelAtIndexPath reload the row.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == myTableView {
lastSelectedFuelAtIndexPath = indexPath
myTableView.reloadRows(at: [indexPath], with: .automatic)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if tableView == myTableView {
lastSelectedFuelAtIndexPath = nil
myTableView.reloadRows(at: [indexPath], with: .automatic)
}
}

Related

How to change image in imageview when tableview cell is expand and collapse in swift

I am using two images for cell, one i am showing when tableview cell is expand and the other one when cell is collapse
when cell expand i am using arrow-bottom
when cell is collapse arrow-right
for cell expand and collapse i am using below code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.cellForRow(at: indexPath) as! FAQTableVIewCell
if selectedIndex == indexPath.row{
if self.isCollapse == false{
cell.arrowImage.image = UIImage(named: "arrow-rightt")
self.isCollapse = true
}else{
cell.arrowImage.image = UIImage(named: "arrow-bottom")
self.isCollapse = false
}
}else{
self.isCollapse = true
}
self.selectedIndex = indexPath.row
tableView.reloadRows(at: [indexPath], with: .automatic)
}
but the above code not working properly, first time when i expand cell its not showing bottom arrow, and if i expand two cells then also its not showing properly, pls do help with code
i need when cell expand then i need to show bottom-arrow, when cell in normal(back to its orginal position or collapsed position) then i need to show right-arrow
When you reload rows, they get in cellForRowAt method.
You must apply changes in this method. Store collapsed indexPath and check it in method.
With array:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//use your cell identifier
let cell = tableView.dequeueReusableCell(withIdentifier: "FAQTableVIewCell", for: indexPath) as! FAQTableVIewCell
let image = collapsedCells.contains(indexPath) ? UIImage(named: "arrow-rightt") : UIImage(named: "arrow-bottom")
cell.image = image
//other settings
return cell
}
var collapsedCells = [IndexPath]()
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//use your height values instead 44 and 120
return collapsedCells.contains(indexPath) ? 44 : 120
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let index = collapsedCells.firstIndex(of: indexPath) {
collapsedCells.remove(at: index)
} else {
collapsedCells.append(indexPath)
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}

Weird display behaviour when selecting tableview row

I have this table view, that populates through Core Data. Everything looks fine, even when scrolling, until I press and hold any row - then that row distorts like in the second image below.
(source: staticflickr.com)
(source: staticflickr.com)
Here's the code to display the tableview
override func viewDidLoad() {
super.viewDidLoad()
animateBackground(colors)
tableView.delegate = self
tableView.dataSource = self
tableView.fetchData(fetchedResultsController as! NSFetchedResultsController<NSFetchRequestResult>)
self.tableView.tableFooterView = UIView(frame: .zero)
}
func numberOfSections(in tableView: UITableView) -> Int {
guard fetchedResultsController.sections?.count != nil else { return 0 }
return fetchedResultsController.sections!.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard fetchedResultsController.sections != nil else { return 0 }
let data = fetchedResultsController.sections![section]
return data.numberOfObjects
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SkillCell", for: indexPath) as! SkillCell
configureCell(cell: cell, indexPath: indexPath as NSIndexPath)
return cell
}
func configureCell(cell: SkillCell, indexPath: NSIndexPath) {
let skill = fetchedResultsController.object(at: indexPath as IndexPath)
cell.skill = skill
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { }
}
From the code above, everything looks normal, yet this distortion occurs. Please help me to see why and how to stop it happening.
As the comment suggests, it's just a visual effect called selectionStyle of your UITableViewCell. Inside your cellForRowAt indexPath method, you can disable it like:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell") as! MyCell
cell.selectionStyle = .none // this removes the effect.
return cell
}
yes you should set tableView selection style to none.
1.Select the tableview in storyboard in the right panel set selection style to none.
or
2.in your tableview cellforrow method set
tableView.selectionstyle = none

How to maintain highlighted multiple UITableView rows after reloading UITableView?

I have a UITableView.
I can select multiple cells make them highlighted.
But, whenever I reload App, the selected and highlighted state disappears.
I think I need to put some codes in 'viewDidAppear' and 'didSelectRowAt'. But I don't have any idea of specific codes.
What do I have to put in this syntax?
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableView.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
}
I recommend u add to dataSource item field selected, and in method cellForRowAtindexPath configure by your dataSource items.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cellClass = (self.cellClass(for: indexPath) ?? self.cellClasses.first) else { return UITableViewCell() }
let cell = tableView.dequeueReusableCell(withIdentifier: cellClass.identifier, for: indexPath)
if let configurable = cell as? ConfigurableComponent, let object = self.object(at: indexPath) {
let item = self.dataSource[indexPath.row]
configurable.selected = item.selected
}
return cell
}
When call didSelectRowAt, just take item and change selected field, sample:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = self.dataSource[indexPath.row]
item.selected = !item.selected
tableView.reloadData()
}

Hide button in another cell when cell is tapped

I have a `tableView with three cells. In two of them I have a button. I would like to hide the button in the other cell, when one of the cells is tapped.
I have tried some solutions in didSelectRowAt but have not been able to hide the buttons:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 1 {
if let cell = tableView.cellForRow(at: indexPath) as? ComposeCell1 {
cell.compose.isHidden = true
if let cell2 = tableView.cellForRow(at: indexPath) as? ComposeCell2 {
cell2.compose.isHidden = true //I can reach the cell from here, but its not hiding the button
}
}
} else if indexPath.row == 2 {
if let cell = tableView.cellForRow(at: indexPath) as? ComposeCell2 {
cell.compose.isHidden = true
}
}
}
Try to track the index for the pressed button with a variable. And use the variable in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell to update the button's visibility. Only thing you need to do in didSelectRowAt is assign the index value the variable and reload the table view
var selectedIndex: Int?
....
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedIndex = indexPath.row
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
.....
cell.compose.isHidden = indexPath.row != selectedIndex
.....
return cell
}

UITableView checkmark hide when scrolling

When I scroll the screen, the upper markings disappear. I've tried some solutions found here, but none worked ...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = players[indexPath.row]
cell.textLabel?.textColor = UIColor.white
cell.backgroundColor = colorForIndex(index: indexPath.row)
cell.textLabel?.font = UIFont(name: "Chalkboard SE", size: 20)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath){
if (cell.accessoryType == .none) {
cell.accessoryType = .checkmark
let player = players[indexPath.row]
playersSelecteds.append(player)
} else {
cell.accessoryType = .none
let player = players[indexPath.row]
if let position = playersSelecteds.index(of: player) {
playersSelecteds.remove(at: position)
}
}
}
}
You should have a model for check-marked cells. because every time you scroll, the cells being reload based on your tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell method.
So, for example add a model like this:
var playersCheckmarked: [Bool] = []
Then add in viewDidLoad some boolean to this array as many as players array have objects. Next in override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method set playersCheckmarked[indexPath.row] = true or playersCheckmarked[indexPath.row] = false based on user selection.
And of course in override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell method add this line:
cell.accessoryType = playersCheckmarked[indexPath.row] == true .checkmark : .none