Selecting TableView Cell Activates Checkmark in Rows in Multiple Sections
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
}
}
Multiple checkMark when row selected in UITableView IOS
[self.tableView cellForRowAtIndexPath:indexPath]
call in the didSelectRowAtIndexPath
will not return the exact cell. It can be same cell, new cell or reused cell. If it is a reused cell at its accessory view has a checkmark, you will end up having two cells with checkmark.
Its better to store in the array and use it accordingly. If you are planning to have multiple selections, Use the code example below.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.cellSelected = [NSMutableArray array];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Cell Initialisation here
if ([self.cellSelected containsObject:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//if you want only one cell to be selected use a local NSIndexPath property instead of array. and use the code below
//self.selectedIndexPath = indexPath;
//the below code will allow multiple selection
if ([self.cellSelected containsObject:indexPath])
{
[self.cellSelected removeObject:indexPath];
}
else
{
[self.cellSelected addObject:indexPath];
}
[tableView reloadData];
}
Add/Remove Multiple Checkmarks on Selected Rows in Swift 4 UITableView
Instead of change accessoryType
on didSelectRowAt
and didDeselectRowAt
methods, you should override and do it on setSelected(_:animated:) from your cell class.
class YourCellClass: UITableViewCell {
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if selected {
accessoryType = .checkmark
} else {
accessoryType = .none
}
}
}
UITableViewCell Checkmark Being Added to multiple rows when one is tapped
Maintain in your Data source which cell is to be selected.
Then in cellForRowAtIndexPath:
if (DropDownItems[indexPath.row].isSelected) {
cell.accessoryType = .Checkmark
} else {
cell.accessoryType = .None
}
and in your didSelectRowAtIndexPath Method:
if(DropDownItems[indexPath.row].isSelected) {
DropDownItems[indexPath.row].isSelected = false
} else {
DropDownItems[indexPath.row].isSelected = true
}
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
how to make limited multiple checkmark in Table View Cell in Swift?
You can't simply add the checkmark to the cell; cell objects will be re-used as the tableview scrolls, so you will lose checkmarks and end up with checkmarks in cells that shouldn't have them.
You need to track the checked cells in another structure; I suggest using a Set<IndexPath>
. You can either allow multi-selection in your tableview, or (my preference) deselect the row after you add the checkmark.
You also need to ensure that your cellForRowAt:
sets the accessory type correctly
class CreateEventStep2VC: UIViewController {
@IBOutlet weak var eventTypeNameLabel: UILabel!
@IBOutlet weak var tableView: UITableView!
var newEvent : [String:Any]!
var eventTypeAvailableData = [String]()
var selectedEventTypes = Set<IndexPath>()
override func viewDidLoad() {
super.viewDidLoad()
// initial value
eventTypeNameLabel.text = ""
// get event Type Data list from EventType data model
eventTypeAvailableData = EventType.allValues.map { $0.toString() }
}
}
extension CreateEventStep2VC : UITableViewDataSource {
//MARK: - UITableViewDatasource
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventTypeAvailableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EventTypeCell", for: indexPath) as! CreateEventStep2Cell
cell.eventTypeNames = eventTypeAvailableData[indexPath.row]
cell.accessoryType = selectedEventTypes.contains(indexPath) ? .checkMark:.none
return cell
}
}
extension CreateEventStep2VC : UITableViewDelegate {
//MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
if selectedEventTypes.contains(indexPath) {
selectedEventTypes.remove(indexPath)
} else if selectedEventTypes.count < 3 {
selectedEventTypes.insert(indexPath)
}
tableView.reloadRows(at: [indexPath], animated:.none)
}
}
Swift - Multiple TableView checkmark - save and load choice
Don't use multiple arrays as data source. That's pretty bad practice and inefficient.
Delete them
var selectedCells = [IndexPath]()
var selectedAreas = [String]()
Declare Area
as struct and add an isSelected
member
struct Area {
let name : String
var isSelected : Bool
init(name : String, isSelected : Bool = false) {
self.name = name
self.isSelected = isSelected
}
}
var areas = [Area(name: "Foo"), Area(name: "Bar")]
In cellForRowAt
assign the checkmark depending on isSelected
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let area = areas[indexPath.row]
cell.textLabel?.text = area.name
cell.accessoryType = area.isSelected ? .checkmark : .none
return cell
}
In didSelectRow
toggle isSelected
and reload the row (yes, only two lines of code)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
areas[indexPath.row].isSelected.toggle()
tableView.reloadRows(at: [indexPath], with: .none)
}
You get the selected areas with
let selectedAreas = areas.filter{$0.isSelected}
and an array of the names
let selectedAreaNames = areas.filter{$0.isSelected}.map{$0.name}
To load and save the names to UserDefaults
add these two methods
func saveSelection()
{
let selectedAreaNames = areas.filter{$0.isSelected}.map{$0.name}
UserDefaults.standard.set(selectedAreaNames, forKey: "selectedNames")
}
func loadSelection()
{
guard let selectedAreaNames = UserDefaults.standard.array(forKey: "selectedNames") as? [String] else { return }
for (index, area) in areas.enumerated() {
areas[index].isSelected = selectedAreaNames.contains(area.name)
}
tableView.reloadData()
}
Swift: Multiple TableView checkmark - select all rows
You have to check if the user selected the first row ("Select all") and update the other rows accordingly:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// toggle the selected area
areas[indexPath.row].isSelected.toggle()
// save the new state for later use
let isSelected = areas[indexPath.row].isSelected
if indexPath.row == 0 {
// "Select all" was selected – update all areas
for i in 1..<areas.count {
areas[i].isSelected = isSelected
}
// update UI
tableView.visibleCells.forEach { $0.accessoryType = isSelected ? .checkmark : .none }
} else {
// update UI
tableView.cellForRow(at: indexPath)?.accessoryType = isSelected ? .checkmark : .none
}
tableView.deselectRow(at: indexPath, animated: true)
}
Recommendation
To separate concerns visually you could also use an own table view section for the "Select all" row. In that case some more changes are necessary:
var areas = [
// you do not need an area for "Select all" any longer
Area(name: "a"),
Area(name: "b"),
Area(name: "c"),
Area(name: "d")
]
var allSelected: Bool {
// helper var to see if all areas are currently selected
return areas.filter({!$0.isSelected}).isEmpty
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 1: return "Areas"
default: return nil
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0: return 1 // select all
case 1: return areas.count
default:
// we should never get here
fatalError()
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.selectionStyle = .none
if indexPath.section == 0 {
cell.textLabel?.text = "Select all"
cell.accessoryType = allSelected ? .checkmark : .none
} else {
let area = areas[indexPath.row]
cell.textLabel?.text = area.name
cell.accessoryType = area.isSelected ? .checkmark : .none
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 {
// (de-)select all
let shouldSelect = !allSelected
for i in 0..<areas.count {
areas[i].isSelected = shouldSelect
}
} else {
areas[indexPath.row].isSelected.toggle()
}
tableView.reloadRows(at: tableView.indexPathsForVisibleRows ?? [], with: .automatic)
}
When i scrolling on UITableview,the checkmark of multiple selected rows are disappears.how to solve this?
The problem lies in this piece of code:
if([_selectedstatearray containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
You are checking if _selectedstatearray contains the specified indexPath
while you store them as NSString [_selectedstatearray addObject:cellText];
Replace the code above with this:
NSString *text = [statearray objectAtIndex:indexPath.row];
if([_selectedstatearray containsObject:text]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
Related Topics
How to Import Existing Objective C Classes in Swift
Error in iOS 10:Unable to Copy Asset Information from Https://Mesu.Apple.Com/Assets/ for Asset Type
Uitableviewcell Selected Background Color on Multiple Selection
How to Debug an Issue with a Release Mode Build in iOS
How to Use Mbprogresshud with Swift
Swiftui Buttonstyle - How to Check If Button Is Disabled or Enabled
How to Get the MAC Os X Firewall to Permanently Allow My iOS App
Leaving Inputaccessoryview Visible After Keyboard Is Dismissed
iOS 7 Device Token Is Different for Same Device
Perform UI Changes on Main Thread Using Dispatch_Async or Performselectoronmainthread
Pop the Current View Using Segues/Storyboard on iOS 5
Passing Data Between 2 Uiviewcontroller Using Delegate and Protocol
Custom View Which Looks Like Uialertview
Why Are Animations on Bounds of an Uilabel Only Working When Increasing the Size