Selecting TableView Cell Activates Checkmark in Rows in Multiple Sections - ios

I've implemented checkmarks (when row is selected) with the following code in cellForRowAt:
// Add a checkmark to row when selected
if selectedIngredients.contains(indexPath.row) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
However, when I select a row, that index.row from each section gets the checkmark:
This seems like it could be because I'm only specifying the indexPath.row, but not the section. How can I code this so that only the selected row within the section I selected gets the checkmark?

use data store for save checkmarks like this:
var selectedIngredients: Set<IndexPath> = [] // use set for unique save
then didSelect callBack:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
if self.selectedIngredients.contains(indexPath) {
self.selectedIngredients.remove(indexPath)
} else {
self.selectedIngredients.insert(indexPath)
}
self.tableView.reloadData()
}
after reload in CellForRow:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if selectedIngredients.contains(indexPath) {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}
If you want it to have only one Row contain checkmark:
var selectedIngredients: IndexPath? = nil
and didSelect CallBack:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
self.selectedIngredients = indexPath
}
and finally:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if selectedIngredients == indexPath {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}

you should add checkmarks in didSelect and remove them in didDeselect methods;
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
// update cell here
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// update cell here
}
also, have a look at this answer; https://stackoverflow.com/a/34962963/13754736

Related

Swift UITableview cell checkmark with selection blink option

My scenario, I am trying to create UITableview single cell checkmark selection and Multiple cell check mark selection. Here, I am trying by below code for single selection check mark but Its reusability not working. Also, I don't know how to do multiple cell selection by clicking cell section.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.deselectRow(at: indexPath, animated: true)
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
For reusability, you need a variable to save the selected cell index(or array for cells) and then set the appropriate accessoryType when displaying the cell.
For single selection, remember to clear the previous selection.
A sample pattern for single selection:
var selectedRow = 0
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedRow = indexPath.row
for cell in tableView.visibleCells { //Why not using didDeselectRowAt? Because the default selected row(like row 0)'s checkmark will NOT be removed when clicking another row at very beginning.
cell.accessoryType = .none
}
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.accessoryType = indexPath.row == selectedRow ? .checkmark : .none
}
A pattern for multiple selections (Updated for multi-sections):
var selectedIndexPaths = Set<IndexPath>()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndexPaths.contains(indexPath) { //deselect
selectedIndexPaths.remove(indexPath)
tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
else{
selectedIndexPaths.insert(indexPath) //select
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.accessoryType = selectedIndexPaths.contains(indexPath) ? .checkmark : .none
}
Model
class Item {
var name:String!
var isSelected = false
}
then inside cellForRowAt
cell.accessoryType = items[indexPath.row].isSelected ? .checkmark : .none
inside didSelectRowAt
items[indexPath.row].isSelected.toggle()
tableView.reloadRows(at:[indexPath],with:.none)
Set isSingleSelection to false for multiple selections and to true for single selection
var isCellSelected = [Bool]()
var isSingleSelection = false
override func viewDidLoad() {
super.viewDidLoad()
for _ in arrayFillingYourTableview { isCellSelected.append(false) }
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = branchTbView.dequeueReusableCell(withIdentifier: "cell")!
cell.accessoryType = isCellSelected[indexPath.row] ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if isSingleSelection {
for i in 0..<isBranchSelected.count {
isCellSelected[i] = false
}
}
isCellSelected[indexPath.row] = ! isCellSelected[indexPath.row]
tableView.reloadData()
}
}

geting multipal checkMark whenever i use didselect method in tableview than its show two check mark ,at a time

I want implement checkMark in tableView cell but when I select cell then Automatically two checkMark show in cell.
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0{
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if indexPath.section == 0{
tableView.cellForRow(at: indexPath)?.accessoryType = .none
//tableView.allowsMultipleSelection = false
}
}
this is my code

TableView CheckMark and Uncheck With Scroll Up Still Checked Cell Value In Ios Swift 4

TableView CheckMark Cell Value Removed After Scrolling Up It will Fix
TableView in You have face a problem many times to Checkmark after scroll Up then Scroll Down To show a Your Checkmark cell is will Removed Because cell is dequeueReusableCell So This Problem Fix , you Have just put Your code and Solved Your Problem.
Any More Help So Send Massage.
Thank you So much. :)
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate{
var temp = [Int]()
var numarr = [Int]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numarr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "id")
cell = UITableViewCell.init(style: .default, reuseIdentifier: "id")
cell?.textLabel?.text = String(numarr[indexPath.row])
if temp.contains(numarr[indexPath.row] as Int)
{
cell?.accessoryType = .checkmark
}
else
{
cell?.accessoryType = .none
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if temp.contains(numarr[indexPath.row] as Int)
{
cell?.accessoryType = .none
temp.remove(at: temp.index(of: numarr[indexPath.row])!)
}
else
{
cell?.accessoryType = .checkmark
temp.append(self.numarr[indexPath.row] as Int)
}
}
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...100
{
numarr.append(i)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
I think if someone were to run your code it would not show any error. But with real data it probably will. The reason is the way you store your checkmarks. You store the data of a row into the temp array when you should be storing the actualy indexPath of the array so that only that row gets the checkmark. In your case, if a row has 1 inside it's label and you click on it, that cell will be highlighted. Now if you start scrolling and another cell contains 1 then that row will also be highlighted.
I have modified your example for the case of a single section. If there is more than one section, you need to store the indexPath instead of indexPath.row.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "id")
cell = UITableViewCell.init(style: .default, reuseIdentifier: "id")
cell?.textLabel?.text = String(numarr[indexPath.row])
if temp.contains(indexPath.row) {
cell?.accessoryType = .checkmark
} else {
cell?.accessoryType = .none
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if temp.contains(indexPath.row) {
cell?.accessoryType = .none
temp.remove(at: indexPath.row)
} else {
cell?.accessoryType = .checkmark
temp.append(indexPath.row)
}
}
You are strongly discouraged from using a second array to keep the selected state.
This is Swift, an object oriented language. Use a custom struct for both num and the selected state.
In didSelectRowAt and didDeselectRowAt change the value of isSelected and reload the row.
And use always the dequeueReusableCell API which returns a non-optional cell.
struct Item {
let num : Int
var isSelected : Bool
}
var numarr = [Item]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numarr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "id", for: indexPath)
let item = numarr[indexPath.row]
cell.textLabel?.text = String(item)
cell.accessoryType = item.isSelected ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
updateSelection(at: indexPath, value : true)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
updateSelection(at: indexPath, value : false)
}
func updateSelection(at indexPath: IndexPath, value : Bool) {
let item = numarr[indexPath.row]
item.isSelected = value
tableView.reloadRows(at: [indexPath], with: .none)
}
override func viewDidLoad() {
super.viewDidLoad()
(0...100).map{Item(num: $0, isSelected: false)}
}

DidselectRow delegate method not working in swift

I have an alert in which I have used table view to show some data.
User can select any item from the table view data.
Now when I'm trying to select any item in didSelectRow method it isn't selecting an item. I have used breakpoints also but it isn't catching the breakpoints also.
I have given its delegates and datasources everything is fine but i'm confused why it isn't working?
My code is this:
extension YourOrdersViewController : UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return PreOrderService.instance.PreOrderModelInstance.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Hello")
print(PreOrderService.instance.PreOrderModelInstance[indexPath.row].perorder_time)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if tableView == orderTableView{
print("Dishes")
}
else{
orderTableView.cellForRow(at: indexPath)?.accessoryType = .none
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = orderTableView.dequeueReusableCell(withIdentifier: "orderCell", for: indexPath) as!
PreOrderTableViewCell
cell.titleLbl.text = PreOrderService.instance.PreOrderModelInstance[indexPath.row].perorder_time
print(cell.titleLbl.text!)
cell.selectionStyle = .none
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.accessoryType = cell.isSelected ? .checkmark : .none
return cell
}
}
View Controller looks like this,
enter image description here
Check or you have set this value:
If No Selection is set instead of Single Selection, the func tableView (_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method will not be executed.
Does it have any gesture recognizer on your UIViewControlller. If it does and the gesture recognizer is above your table views on responder chain, it will take any single touch and leave nothing for your table views.
Whole problem in your code I think is:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
self.tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
In Main.storyboard select your table view and in Attribute inspector change selection to single selection
Make sure that the delegate and datasource are set.
If you're creating the views via storyboard, make sure that you set the iboutlets for delegate/datasource.
Both of these lines mean the same thing: so remove the second one.
cell.selectionStyle = .none
cell.selectionStyle = UITableViewCellSelectionStyle.none

How to deselect selected cell in UITableView

Normally, when I touch UITableViewCell, then UITableViewCell is selected and highlighted.
But, again touch exactly same UITableViewCell, then nothing happen.
I want that if I touch selected UITableViewCell, then UITableVIewCell to deselect.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) else { return }
if cell.isSelected == true {
cell.isSelected = false
}
}
/////
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) else { return }
if cell.isSelected == false {
cell.isSelected = true
} else {
cell.isSelected = false
}
}
Both source code does not working. How do I fix this method?
Minimal working example (first 7 cells are selectable):
import UIKit
import PlaygroundSupport
class MyTableViewController: UITableViewController {
var selectedIndexPath: IndexPath? = nil
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndexPath == indexPath {
// it was already selected
selectedIndexPath = nil
tableView.deselectRow(at: indexPath, animated: false)
} else {
// wasn't yet selected, so let's remember it
selectedIndexPath = indexPath
}
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyTableViewController()

Resources