Reputation: 13883
I am new in programming and iOS Development, I need to make table view that has multiple limited checkmark.
I mean, I want to allow the user to select maximum 3 items (not just 1, but also not all of item in the table view can be selected) in the table view, I have tried but I haven't gotten what I want, I just can select one only item in table view
here is the code I use
import UIKit
class CreateEventStep2VC: UIViewController {
@IBOutlet weak var eventTypeNameLabel: UILabel!
@IBOutlet weak var tableView: UITableView!
var newEvent : [String:Any]!
var eventTypeAvailableData = [String]()
var selectedEventTypes = [String]()
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]
return cell
}
}
extension CreateEventStep2VC : UITableViewDelegate {
//MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
}
}
}
could you please help me ?
Upvotes: 0
Views: 821
Reputation: 100549
You can have array of indexPath rows allArr
like this
1- when user selects more than 3 the first one will be automatically dropped
var allArr = [Int]()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
allArr.append(indexPath.row)
}
if(allArr.count == 4)
{
allArr.dropFirst()
}
}
2- add this to cellForRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EventTypeCell", for: indexPath) as! CreateEventStep2Cell
cell.eventTypeNames = eventTypeAvailableData[indexPath.row]
if allArr.contains(indexPath.row) {
cell.accessoryType = .checkmark
}
else
{
cell.accessoryType = .none
}
return cell
}
3- remove code in didSelectRowAt
Upvotes: 0
Reputation: 115076
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)
}
}
Upvotes: 2