I have a table view, in which I have the items with check boxes. Users can select any items (multiselection also) and they can press the Proceed button to pay.
I was using a button as a check box. So if the user presses the button, or they select a table row, both cases are handled the function.
So now, my proceed buton starts as disabled. Whenever the user presses any items using the didSelectRowAt method or check box button action, only then the Proceed button will be enabled.
But now, whenever I press the first item or the first check box button, my proceed button is not getting enabled. If I press the second item or the second check box, it works. I don't know why.
Here is my code of didSelectRowAt and my check box button action code:
#Updated:
var selectedIndexPathArray = Array<NSIndexPath>()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "itemcell", for: indexPath) as! itemTableViewCell
cell.checkboxBtn.isUserInteractionEnabled = false
if selectedIndexPathArray.contains(indexPath as NSIndexPath) {
cell.checkboxBtn.setImage(UIImage(named: "enabled"), for: .normal)
proceedbutton.isUserInteractionEnabled = true
} else {
cell.checkboxBtn.setImage(UIImage(named: "disabled"), for: .normal)
proceedbutton.isUserInteractionEnabled = false
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndexPathArray.contains(indexPath as NSIndexPath) {
let index = selectedIndexPathArray.index(of: indexPath as NSIndexPath)
selectedIndexPathArray.remove(at: index!)
} else {
selectedIndexPathArray.append(indexPath as NSIndexPath)
}
tableView.reloadData()
}
Thanks in advance!
Yes because first time if you click on button then proceedbutton will be called and at that time selectedIndexPathArray will have no any value means nil.
So first time your else part will be executed.
.
.
.
else {
selectedIndexPathArray.append(indexPath! as NSIndexPath)
cell?.checkboxBtn.setImage(UIImage(named: "disabled"), for: .normal)
proceedbutton.isUserInteractionEnabled = false
}
And when you press agin then your if condition will be true so it will be enable
Try this on your if-else condition on your proceed() function.
if selectedIndexPathArray.contains(indexPath! as NSIndexPath) {
electedIndexPathArray.remove(at: index!)
cell?.checkboxBtn.setImage(UIImage(named: "disabled"), for: .normal)
proceedbutton.isUserInteractionEnabled = false
}
else {
selectedIndexPathArray.append(at: index!)
cell?.checkboxBtn.setImage(UIImage(named: "enabled"), for: .normal)
proceedbutton.isUserInteractionEnabled = true
}
Remove selector for button in cell and default set userInteraction for button is false.No need to set it everytime. Perform everything on didSelectRow.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: itemscell, for: indexPath) as! itemsTableViewCell
cell?.checkboxBtn.isUserInteractionEnabled = false
if selectedIndexArray.contains(indexPath.row) {
cell.checkboxBtn.setImage(UIImage(named: "enabled"), for: .normal)
proceedbutton.isUserInteractionEnabled = true
} else {
cell.checkboxBtn.setImage(UIImage(named: "disabled"), for: .normal)
proceedbutton.isUserInteractionEnabled = false
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndexArray.contains(indexPath.row) {
let index = selectedIndexPathArray.index(of: indexPath.row)
selectedIndexArray.remove(at: index!)
} else {
selectedIndexArray.append(indexPath.row)
}
tableView.reloadData()
}
Related
My task I am trying to show tableView with check box button inside the popup viewcontroller.
Whenever user click the button it is changing check and uncheck but I need to do when I click done button I have to keep user checked and if click cancel it should uncheck(which is user checked before click cancel). I need to understand and fix this task.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
cell.myCellLabel.text = self.animals[indexPath.row]
if selectedRows.contains(indexPath)
{
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
}else{
cell.checkBox.setImage(UIImage(named:"uncheck.png"), for: .normal)
}
cell.checkBox.tag = indexPath.row
cell.checkBox.addTarget(self, action: #selector(checkBoxSelection(_:)), for: .touchUpInside)
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) as? MyCustomCell else {
return
}
if self.selectedRows.contains(indexPath) {
self.selectedRows.remove(at: self.selectedRows.index(of: indexPath)!)
cell.checkBox.setImage(UIImage(named:"uncheck.png"), for: .normal)
} else {
self.selectedRows.append(indexPath)
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
let indexPath = tableView.indexPathForSelectedRow //optional, to get from any UIButton for example
let currentCell = tableView.cellForRow(at: indexPath!) as! MyCustomCell
}
}
#IBAction func cancelPopup(_ sender: Any) {
self.removeAnimate()
}
#IBAction func donePopUp(_ sender: AnyObject) {
self.removeAnimate()
}
You may consider using basic taleview cell with setting acessoryType . Putting checkbox and labels all at the left seems giving poor UX
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DefectCell", for: indexPath)
let category = defectSet [indexPath.section]
let item = category.items[indexPath.row]
cell.textLabel?.text = item.name
cell.selectionStyle = .none
let isFound = User.shared.selectedDefect.filter{ $0.id == item.id }.count > 0
if (isFound)
{
cell.accessoryType = .checkmark
}
else
{
cell.accessoryType = .none
}
return cell
}
i have added data in table view and i have manually added "select all" option in to list at first position now when user select first option which is select all then all item in to list should be selected and deselected when choose same. i have tried code below but its not working so can any one help me to solve this
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = ObjTableview.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! SelectUserCell
for i in 0 ..< self.getStudentName.count {
cell.btnCheckbox.setImage(UIImage(named: "selectedItem"), for: .normal)
print (i) //i will increment up one with each iteration of the for loop
}
}
var unchecked = true
#IBAction func btnCheckBoxClick(_ sender: Any) {
if unchecked == true {
//(sender as AnyObject).setImage(UIImage(named: "selectedItem"), for: .normal)
cell?.btnCheckbox.setImage(UIImage(named: "selectedItem"), for: .normal)
//unchecked = false
let cello = ObjTableview.cellForRow(at: indexPath!)
print(cello!)
ObjTableview.reloadData()
}else
{
//(sender as AnyObject).setImage(UIImage(named: "unSelectedItem"), for: .normal)
cell?.btnCheckbox.setImage(UIImage(named: "unSelectedItem"), for: .normal)
// unchecked = true
}
}
Jayprakash, You are almost there. You need to modify some lines -
Here is your modified code snippet
var unchecked:Bool = true
#IBAction func btnCheckBoxClick(_ sender: Any) {
if(unchecked){
unchecked = false
}
else{
unchecked = true
}
ObjTableview.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if(indexPath.row == 0){
btnCheckBoxClick(sender: UIButton())
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell : SelectUserCell!
cell = tableView .dequeueReusableCell(withIdentifier: "SelectUserCell", for: indexPath) as! SelectUserCell
cell.selectionStyle = UITableViewCellSelectionStyle.none
if(unchecked){
cell.btnCheckbox.setImage(UIImage(named: "unSelectedItem"), for: .normal)
}
else{
cell.btnCheckbox.setImage(UIImage(named: "selectedItem"), for: .normal)
}
// Do your stuff here
return cell
}
Hop it will simplify your code structure.
in my cellForRowAt Im inflating my xib and setting its content:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TableViewCell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! TableViewCell
cell.label.text = data[indexPath.row]
let tap = UIGestureRecognizer(target: self, action: #selector(tableCellTap(_:cell:)))
cell.addGestureRecognizer(tap)
cell.selectionStyle = .none
cell.checkBox.isUserInteractionEnabled = false
cell.checkBox.boxType = .circle
cell.checkBox.markType = .radio
cell.checkBox.cornerRadius = 0
cell.checkBox.stateChangeAnimation = .expand(.fill)
if (indexPath.row == selectedIndex){
cell.checkBox.checkState = .checked
}else{
cell.checkBox.checkState = .unchecked
}
return cell
}
Then Im setting my deselect and select values
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
cell.checkBox.checkState = .checked
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
cell.checkBox.checkState = .unchecked
}
I need a sense of direction in how i can make it select and deselect the same row and update my xib file checkbox?
m13checkbox is being used
when i click on the cell for the first time it selects it but when i click on the same cell again it does not call it and does nothing until a loop a completed in the checkboxes
you don't need didDeselectRowAt, you can achieve the same functionality by checking if the radio button is checked in your didSelectRowAt.
If the radio button is checked, simply uncheck it and vice versa.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
if(cell.checkBox.isChecked){
cell.checkBox.checkState = .unchecked
}else{
cell.checkBox.checkState = .checked
}
}
Apple has already given very good sample code for that on its website,
you can check at:https://developer.apple.com/library/content/samplecode/TableMultiSelect/Introduction/Intro.html
I have a scenario where a UITableView shows a list of players in a league.
The user selects two players to compare results. As a user selects a player a check is shown. Once the user has selected two users a new VC is presented, showing the results of the two players.
On this ResultsVC I have a back button which dismisses ResultsVC, and the view is returned to the originalVC.
Upon returning to this originalVC the checks next to the players which were selected for viewing are still visible.
How do I reset all checks when this VC is returned to?
This is my code for the original VC with the TableView:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PersonalStatsTableViewCell", for: indexPath as IndexPath) as! PersonalStatsTableViewCell
cell.textLabel?.text = self.communityPlayers[indexPath.row]
cell.textLabel?.font = UIFont(name: "Avenir", size: 12)
cell.textLabel?.textColor = UIColor.white // set to any colour
cell.layer.backgroundColor = UIColor.clear.cgColor
cell.personalStatsInfoButton.tag = indexPath.row
cell.personalStatsInfoButton.addTarget(self, action: #selector(infoClicked), for: UIControlEvents.touchUpInside)
cell.selectedBackgroundView?.backgroundColor = UIColor.red
return cell
}
func infoClicked(sender:UIButton){
let buttonRow = sender.tag
self.friendId = self.communityPlayerIds[buttonRow]
self.personalSelf = false
self.friendName = self.communityPlayers[buttonRow]
self.performSegue(withIdentifier: "personalStatsSegue", sender: self)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedCellTitle = self.communityPlayers[indexPath.row]
cellId = indexPath.row
//print (self.communityPlayerIds[indexPath.row])
if let cell = tableView.cellForRow(at: indexPath) {
if cell.isSelected {
cell.accessoryType = .checkmark
}
}
if let sr = tableView.indexPathsForSelectedRows {
print("didSelectRowAtIndexPath selected rows:\(sr)")
if sr.count == 2{
let tempId_1 = sr[0][1]
let tempId_2 = sr[1][1]
self.tempCount = 2
self.tempPlayerId_1 = self.communityPlayerIds[tempId_1]
self.tempPlayerId_2 = self.communityPlayerIds[tempId_2]
print ("you have selected player I'ds: ", self.tempPlayerId_1!, "and ", self.tempPlayerId_2!)
self.performSegue(withIdentifier: "showHeadToHeadSegue", sender: self)
}
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath as IndexPath) {
cell.accessoryType = .none
}
if let sr = tableView.indexPathsForSelectedRows {
print("didDeselectRowAtIndexPath selected rows:\(sr)")
}
}
}
I have read around the subject but nothing appears to work.
sussed it.
I added
cell.accessoryType = .none
into the func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell function
Then when the view is returned all checks are removed.
In my cellForRowAtIndexPath I add tags to my cells as:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:people = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! people
cell.fullName.text = self.fullNames[indexPath.row]
cell.viewProfile.tag = indexPath.row
temp = cell.viewProfile.tag
cell.viewProfile.addTarget(self, action: "viewProfile:", forControlEvents: .TouchUpInside)
return cell
}
where
var temp = 0
on the top, under the class declaration.
And when I try later:
func viewProfile(sender: UIButton) {
print(temp)
}
it returns me 2, the same value on each time. Why? What I do wrong?
If you are trying to get the index of the button that is clicked. Then try this
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:people = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! people
cell.fullName.text = self.fullNames[indexPath.row]
cell.viewProfile.tag = indexPath.row
cell.viewProfile.addTarget(self, action: "viewProfile:", forControlEvents: .TouchUpInside)
return cell
}
func viewProfile(sender: UIButton) {
print("Index : \(sender.tag)")
}
No need of temp variable.
I think you should override the method didSelectRowAtIndexPath to show the indexPath.row. You are always printing the same value because in the case you run the cellForRowAtIndexPath it's always run until the last cell that display on your view. So you always get the same value of temp var.