I try to use standard selection in isEditing mode. When I press the first time it's selected, but when I press the second time it stays selected visually. If I change isEditing to false and next time set it true I can't select rows which were selected previously but they don't mark.
How to fix it? isEditing change by button.
enter image description here
'''
class PermanentInternalViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, UIGestureRecognizerDelegate {
var index = 0
var test = ["dghffhfh",
"sadasdsa",
"sgfhghgfh"
]
var selectedArray: [IndexPath] = []
#IBOutlet weak var tableViewInternal: UITableView!
#IBOutlet weak var createButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(tableTapped))
self.tableViewInternal.addGestureRecognizer(tap)
self.tableViewInternal.delegate = self
self.tableViewInternal.dataSource = self
self.tableViewInternal.tableFooterView = UIView()
self.tableViewInternal.allowsMultipleSelectionDuringEditing = true
createButton.layer.cornerRadius = 10
if tableViewInternal.isEditing {
createButton.titleLabel!.text = "Add to your Temporary List"
} else {
createButton.titleLabel!.text = "Create Temporary List"
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
test.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "permanentInsideCell1", for: indexPath) as! customCell
cell.tf.delegate = self
// cell.selectionStyle = .none
cell.tf.text = test[indexPath.row]
cell.tf.isUserInteractionEnabled = false
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! customCell
cell.tf.isUserInteractionEnabled = true
cell.selectionStyle = .none
cell.tf.becomeFirstResponder()
index = indexPath.row
if tableViewInternal.isEditing{
cell.tf.isUserInteractionEnabled = false
}
print (cell.isSelected)
if selectedArray.contains(indexPath) {
// it was already selected
selectedArray.remove(at: selectedArray.firstIndex(of: indexPath)!)
print(selectedArray)
} else {
// wasn't yet selected, so let's remember it
selectedArray.append(indexPath)
print(selectedArray)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
print("Deselect")
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
test.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
test[index] = textField.text!
tableViewInternal.reloadData()
// textField.resignFirstResponder()
}
#IBAction func createTempList(_ sender: UIButton) {
tableViewInternal.isEditing = true
createButton.setTitle("Add to your Temporary List", for: .normal)
}
func addAction() {
// create a new row by appending new empty strings
test.append("")
tableViewInternal.reloadData()
}
#objc func tableTapped(tap:UITapGestureRecognizer) {
tap.cancelsTouchesInView = false
let location = tap.location(in: self.tableViewInternal)
let path = self.tableViewInternal.indexPathForRow(at: location)
if let _ = path {
// self.tableView(self.tableViewInternal, didSelectRowAt: indexPathForRow)
} else {
// handle tap on empty space below existing rows however you want
if self.tableViewInternal.isEditing {
self.tableViewInternal.isEditing = false
self.createButton.setTitle("Create Temporary List", for: .normal)
} else {
addAction()
}
}
}
}
'''
Solved.
Problem was in cell.selectionStyle = .none
If remove it and use a clear background color for tableview all is working.
Related
I have a stackView(vertical) which contains labels and bottom description label is hidden by default. And I implemented an arrow button at the right side of the cell. By clicking the button, I just want to show the hidden description label and stackView should expand automatically and make cell bigger. This was my basic idea to implement expandable cell.
So this is the code I used to get desired results:
#objc func downArrowButtonClicked(_ sender: UIButton){
let indexPath = IndexPath(row: sender.tag, section: 0)
selectedIndex = indexPath
selectedCellIndex = sender.tag
isDescHidden = !isDescHidden
tableView.reloadRows(at: [indexPath], with: .automatic)
}
Above is the code for the button inside clicked cell. I went with the idea to reload that particular index. I created a variable named selectedCellIndex of in which I use in cellForRowAt method to make some changes.
I also had the implement some code in viewDidLayoutSubviews() as when I first clicked the cell wasn't getting expanded fully. here's that just in case:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let indexPath = selectedIndex
tableView.reloadRows(at: [indexPath ?? IndexPath(row: 0, section: 0)], with: .automatic)
}
And calling it in willDisplay method which finally fixed the cell expansion issue:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
viewDidLayoutSubviews()
}
And here is my cellForRowAt function:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
if indexPath.row == 0 {
cell.lblTitle.text = "Title 1"
cell.lblDesc.text = "Desc 1"
}
else if indexPath.row == 1 {
cell.lblTitle.text = "Title 2"
cell.lblDesc.text = "Desc 2"
}
else {
cell.lblTitle.text = "Title 3"
cell.lblDesc.text = "Desc 3"
}
if selectedCellIndex != nil {
if isDescHidden == false {
if cell.isDescHidden == true {
cell.lblDesc.isHidden = false
cell.btnArrow.setImage(UIImage(systemName: "chevron.up"), for: .normal)
}
else {
cell.lblDesc.isHidden = true
cell.btnArrow.setImage(UIImage(systemName: "chevron.down"), for: .normal)
}
}
else {
if cell.isDescHidden == true {
cell.lblDesc.isHidden = true
cell.btnArrow.setImage(UIImage(systemName: "chevron.down"), for: .normal)
}
else {
cell.lblDesc.isHidden = false
cell.btnArrow.setImage(UIImage(systemName: "chevron.up"), for: .normal)
}
}
cell.isDescHidden = !cell.isDescHidden
}
cell.btnArrow.tag = indexPath.row
cell.btnArrow.addTarget(self, action: #selector(downArrowButtonClicked(_:)), for: .touchUpInside)
return cell
}
This approach gets too confusing as you can see from the above code. The isDescHidden variable is defined in both Main view controller as well as table view cell class and I was trying to use both to expand or collapse a particular cell. However first time it works but if I have 3 cells expanded, collapsing button click doesn't work for 1-2 clicks then works.
Is there a better approach for this kind of problem? Or is there any way I can directly set cell.isDescHidden value from #objc func downArrowButtonClicked(_ sender: UIButton) function? So I can use that in cellForRowAt function?
I would be glad if I could directly make changes to cell variables from that.
Use the following function for automatic height for rows and provided top and bottom constraints to your stackView
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Here is my CustomCell
class CustomCell: UITableViewCell {
#IBOutlet weak var titleCell: UILabel!
#IBOutlet weak var detail: UILabel!
#IBOutlet weak var arrowButton: UIButton!
let upArrow = UIImage(systemName: "chevron.up.circle.fill")
let downArrow = UIImage(systemName: "chevron.down.circle.fill")
var onArrowClick: ((UIButton)->())!
#IBAction func handleArrowButton(sender: UIButton){
onArrowClick(sender)
}
func updateArrowImage(expandStatus: Bool){
arrowButton.setImage(expandStatus ? downArrow : upArrow, for: .normal)
}
}
For sample Data
let data = [
["Nothing", "description is very long description is very long description is very long description is very "],
["Nothing", "description is very long "],
["Nothing", "description is very long "],
["Nothing", "description is very long "],
["Nothing", "description is very long "]
]
var eachCellStatus: [Bool] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
for _ in data {
eachCellStatus.append(true)
}
}
TableView methods are like this
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomCell
cell.titleCell.text = data[indexPath.row][0]
cell.detail.text = data[indexPath.row][1]
cell.detail.isHidden = eachCellStatus[indexPath.row]
cell.updateArrowImage(expandStatus: self.eachCellStatus[indexPath.row])
cell.onArrowClick = { button in
self.eachCellStatus[indexPath.row].toggle()
cell.updateArrowImage(expandStatus: self.eachCellStatus[indexPath.row])
tableView.reloadRows(at: [indexPath], with: .automatic)
}
return cell
}
First create a model to show data into cell. You have to preserve the state of cell.
struct CellData {
var title: String
var details: String
var isExpanded: Bool
}
In CustomTableViewCell add a property for cellData and assign Outlets data from it. Also create a protocol to reload row from UIViewController
protocol CustomTableViewCellDelegate {
func reloadRow(sender: CustomTableViewCell, flag: Bool)
}
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var detailsLabel: UILabel!
#IBOutlet weak var showButton: UIButton!
var indexPath: IndexPath?
var delegate: CustomTableViewCellDelegate?
var data: CellData? {
didSet {
if let data = data {
if data.isExpanded == false {
detailsLabel.isHidden = true
showButton.setImage(UIImage(systemName: "chevron.down"), for: .normal)
}else {
detailsLabel.isHidden = true
showButton.setImage(UIImage(systemName: "chevron.up"), for: .normal)
}
titleLabel.text = data.title
detailsLabel.text = data.details
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
titleLabel.text = nil
detailsLabel.text = nil
}
#IBAction func showButtonAction(_ sender: UIButton) {
if var data = data {
data.isExpanded.toggle()
delegate?.reloadRow(cell: self, flag: data.isExpanded)
}
}
}
In UIViewController add an array of CellData type. You may assign it's data in viewDidLoad() method.
var tableData: [CellData]
Modify numberOfRowsInSection() and cellForRow() method like bleow.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
cell.data = tableData[indexPath.row]
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Then confirm CustomTableViewCellDelegate protocol to UIViewController
extension ViewController: CustomTableViewCellDelegate {
func reloadRow(sender: CustomTableViewCell, isExpanded: Bool) {
guard let tappedIndexPath = tableView.indexPath(for: sender) else { return }
tableData[tappedIndexPath.row].isExpanded = isExpanded
tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.automatic)
}
}
I create a custom cell that include tableview
Here's the MainTableView and data
var data = [People(name:"Kevin",age:"18",tall:"180")]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainCell", for: indexPath) as! MainTableViewCell
cell.title = data[indexPath.row].name
cell.detail = ["age \(data[indexPath.row].age)","tall \(data[indexPath.row].tall)"]
cell.isExtend = false
return cell
}
I try to tap cell to expand tableView height and load data
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainCell", for: indexPath) as! MainTableViewCell
cell.isExpand = !cell.isExpand
}
Here's the MainTableViewCell
class MainTableViewCell: UITableViewCell {
#IBOutlet weak var title: UILabel!
#IBOutlet weak var detailTableView: UITableView!
#IBOutlet weak var detailTableViewHeight: NSLayoutConstraint!
var detail:[String] = []{
didSet{
detailTableView.reloadData()
}
}
var isExpand: Bool = false{
didSet{
detailTableView.isHidden = !isExpand
detailTableView.reloadData()
detailTableViewHeight.constant = isExpand ? detailTableView.contentSize.height:0
}
}
override func awakeFromNib() {
super.awakeFromNib()
detailTableView.delegate = self
detailTableView.dataSource = self
detailTableView.isScrollEnabled = false
detailTableViewHeight.constant = 0
}
}
I use tableView to load data and hide some of theme first, and tapped to show and hide theme
but It happened nothing
Did I forgot something?
In cellforRowAt:
let cell: MoreUserDetails = tableView.dequeueReusableCell(withIdentifier: "MoreUserDetails") as! MoreUserDetails
cell.backgroundColor = .clear
cell.selectionStyle = .none
if isExpand {
// your func when its expanded
}
else {
// your func when its hidden
}
return cell
in did select
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
if isSelected[indexPath.row] {
isExpand[indexPath.row] = false
}
else {
isExpand[indexPath.row] = true
}
self.tableVIew.reloadData()
}
I have a textField, which when touch displays a tableView with some rows.
I'm trying to do this: when a user selects one of the rows, the value of row is placed in the textField and the tableView is closed.
The first part works well for me. The user touch on one row and the textField shows the value of that row. But if I want to close the tableview, I have to press twice on the row.
This is my code:
class Redactar_mensaje: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
var values = ["123 Main Street", "789 King Street", "456 Queen Street", "99 Apple Street", "red", "orange", "yellow", "green", "blue", "purple", "owaldo", "ostras", "Apple", "Pineapple", "Orange", "Adidas"]
#IBOutlet weak var campo_para: UITextField!
#IBOutlet weak var tableView: UITableView!
var originalCountriesList:[String] = Array()
override func viewDidLoad() {
super.viewDidLoad()
tableView.isHidden = true
for country in values {
originalCountriesList.append(country)
}
campo_para.delegate = self
tableView.delegate = self
tableView.dataSource = self
campo_para.addTarget(self, action: #selector(textFieldActive), for: UIControlEvents.touchDown)
campo_para.addTarget(self, action: #selector(searchRecords(_ :)), for: .editingChanged)
}
#objc func searchRecords(_ textField: UITextField) {
self.values.removeAll()
if textField.text?.count != 0 {
for country in originalCountriesList {
if let countryToSearch = textField.text{
let range = country.lowercased().range(of: countryToSearch, options: .caseInsensitive, range: nil, locale: nil)
if range != nil {
self.values.append(country)
}
}
}
} else {
for country in originalCountriesList {
values.append(country)
}
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return values.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cellx")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cellx")
}
cell?.textLabel?.text = values[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
campo_para.text = values[indexPath.row]
tableView.isHidden = true //I need press twice for this. I want press only one
}
func textFieldActive() {
tableView.isHidden = false
}
}
Ideally, the user touches the textField, displays the tableView, chooses one of the values, and it close automatically the tableView. But this last one does not work well.
Any advice?
Details
xCode 8.3, Swift 3.1
Example to Detect Double tap and Single tap on TableViewCell
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.tableFooterView = UIView()
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
cell.label.text = "\(indexPath)"
cell.delegate = self
return cell
}
}
extension ViewController:TableViewCellDelegate {
func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell) {
let indexPath = tableView.indexPath(for: cell)
print("singleTap \(String(describing: indexPath)) ")
}
func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell) {
let indexPath = tableView.indexPath(for: cell)
print("doubleTap \(String(describing: indexPath)) ")
//You can hide your textfield here
}
}
TableViewCell.swift
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
private var tapCounter = 0
var delegate: TableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
addGestureRecognizer(tap)
}
func tapAction() {
if tapCounter == 0 {
DispatchQueue.global(qos: .background).async {
usleep(250000)
if self.tapCounter > 1 {
self.doubleTapAction()
} else {
self.singleTapAction()
}
self.tapCounter = 0
}
}
tapCounter += 1
}
func singleTapAction() {
delegate?.tableViewCell(singleTapActionDelegatedFrom: self)
}
func doubleTapAction() {
delegate?.tableViewCell(doubleTapActionDelegatedFrom: self)
}
}
TableViewCellDelegate.swift
import UIKit
protocol TableViewCellDelegate {
func tableViewCell(singleTapActionDelegatedFrom cell: TableViewCell)
func tableViewCell(doubleTapActionDelegatedFrom cell: TableViewCell)
}
Result
Here I put my solution, in case someone else would happen something similar.
Just change the order of the lines and add one more line. First it makes it invisible and then puts the result in the textField and, magically, it worked!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.isHidden = true
campo_para.text = NombreUsuario[indexPath.row]
campo_asunto.becomeFirstResponder()
}
Thanks!
How to show button Highlight colour,,and the colour is red
extension LeaveDetailVC: cellIndexCall{
func selectBtnIndex(sender: UIButton) {
let buttonPosition:CGPoint = sender.convert(.zero, to:leaveDetailTableView)
var indexPath = leaveDetailTableView.indexPathForRow(at: buttonPosition)
self.indexPath = indexPath!
print("\(String(describing: indexPath?.row))") /* index path of button
self.menuClickIndex = (indexPath?.row)!
}
}
And my Button is cover the tableViewCell.
And I also create a button delegate in cell class and call in viewController through extension.
I just want to highlight button and that is over cell.
override func tableView(_ tableView: UITableView, shouldHighlightRowAt
indexPath: IndexPath) -> Bool {
return true
}
override func tableView(_ tableView: UITableView, didHighlightRowAt
indexPath:
IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell?.contentView.backgroundColor = UIColor.orange
cell?.backgroundColor = UIColor.orange
}
override func tableView(_ tableView: UITableView, didUnhighlightRowAt
indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell?.contentView.backgroundColor = UIColor.black
cell?.backgroundColor = UIColor.black
}
In your viewController
class LeaveDetailVC: ViewController {
var selectedRows: [IndexPath] = [] // i assume multiple select button
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_CELL") as! YOUR_CELL_CLASS
cell.isHighlight = selectedRows.indices.contains(indexPath) // Determine if cell was selected or not
}
}
extension LeaveDetailVC: cellIndexCall {
func selectBtnIndex(sender: UIButton) {
let buttonPosition:CGPoint = sender.convert(.zero, to:leaveDetailTableView)
var indexPath = leaveDetailTableView.indexPathForRow(at: buttonPosition)
if selectedRows.indices.contains(indexPath) {
if let index = selectedRows.index(of: indexPath) {
self.selectedRows.remove(at: index) // remove selected indexpath
}
} else {
self.selectedRows.append(indexPath) // add selected indexpath
}
}
}
In your cell class
var isHighlight: Bool = false
override func layoutSubviews() {
super.layoutSubviews()
// TODO : Set your button color based on isHighlight flag
}
Im using a tableview to display an array of strings. When I click on a particular row, I want it to be highlighted with a checkmark. When I deselect a row, I want the checkmark to be removed. When I press a button, I want the rows that are currently highlighted to be passed out in an array(newFruitList).
My problem is that when I click the first row, the last is highlighted. When I uncheck the first row, the last is unchecked, as if they are the same cell?
How do I overcome this?
Also, the way I am adding and removing from my new array, is this the correct way to go about doing this?
Thanks
My Code:
class BookingViewController: UIViewController, ARSKViewDelegate, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var table: UITableView!
let fruits = ["Apples", "Oranges", "Grapes", "Watermelon", "Peaches"]
var newFruitList:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
self.table.dataSource = self
self.table.delegate = self
self.table.allowsMultipleSelection = true
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = table.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil{
cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
}
cell?.textLabel?.text = fruits[indexPath.row]
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
newFruitList.append(fruits[indexPath.row])
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let index = newFruitList.index(of: fruits[indexPath.row]) {
newFruitList.remove(at: index)
}
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
}
}
#IBAction func bookButtonPressed(_ sender: UIButton) {
//testing purposes
for i in stride(from: 0, to: newFruitList.count, by: 1){
print(newFruitList[i])
}
}
They are probably the same cell because you use dequeueReusableCell and it reuses old cells.
use:
override func prepareForReuse() {
super.prepareForReuse()
}
To reset the cell and it should be fine.
As for the save and send mission. Create an pre-indexed array that you can populate.
var selected: [Bool] = []
var fruits: [Fruit] = [] {
didSet {
selected = Array(repeating: false, count: fruits.count)
}
}
And in your didSelectItemAt you do:
selected[indexPath.item] = !selected[indexPath.item]
UITableView reuses the cell that is already present and hence you will see that duplicate check mark, so to solve this issue you need to clear the cell states while loading cell. for that you can create a model with property to track the states of your selected cells
So your fruit model must be like below
class Fruit{
var name:String
var isSelected:Bool
init(name:String){
isSelected = false
self.name = name
}
}
Then you will have table view populated with Fruit list
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = table.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil{
cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
}
let model = fruits[indexPath.row]
cell?.textLabel?.text = model.name
if(model.isSelected){
cell.accessoryType = .checkmark
}
else{
cell.accessoryType = .none
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
newFruitList.append(fruits[indexPath.row])
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
var model = fruits[indexPath.row]
model.isSelected = true
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let index = newFruitList.index(of: fruits[indexPath.row]) {
newFruitList.remove(at: index)
}
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
var model = fruits[indexPath.row]
model.isSelected = false
}
}