1

Let say I have 10 UIButton like below

enter image description here

I want to implement single selection but I have no idea how to do this. The condition is like below :

At first, the ALL button will in selected position(highlight or etc). When I click another button like VCU button, the VCU button will highlight And the ALL button will in normal state(unhighlight).

Snippet code :

@IBAction func buttonDisplayAction(_ sender: UIButton) {
    if sender == self.buttonAll {
        self.currNr = -1
        self.filteredDataRoomStatus = self.dataRoomStatus
    } else if sender == self.buttonVCU {
        self.currNr = 1
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "zistatus", searchStr: "\(self.currNr)", equalFlag: true)
    } else if sender == self.buttonOC {
        self.currNr = 5
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "zistatus", searchStr: "\(self.currNr)", equalFlag: true)
    } else if sender == self.buttonVCC {
        self.currNr = 0
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "zistatus", searchStr: "\(self.currNr)", equalFlag: true)
    } else if sender == self.buttonVD {
        self.currNr = 2
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "checkout zistatus", searchStr: "0 2", equalFlag: false)
    } else if sender == self.buttonED {
        self.currNr = 3
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "zistatus", searchStr: "\(self.currNr)", equalFlag: true)
    } else if sender == self.buttonOD {
        self.currNr = 4
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "zistatus", searchStr: "\(self.currNr)", equalFlag: true)
    } else if sender == self.buttonCO {
        self.currNr = 12
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "checkout", searchStr: "1", equalFlag: true)
    } else if sender == self.buttonDnD {
        self.currNr = 8
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "zistatus", searchStr: "\(self.currNr)", equalFlag: true)
    } else if sender == self.buttonOOO {
        self.currNr = 6
        self.isButtonSelected = true
        self.filteredDataRoomStatus = filterArray(dataRoomStatus, keywords: "zistatus", searchStr: "\(self.currNr)", equalFlag: true)
    }

    do {
        let currButton: UIButton = (sender as UIButton)
        currButton.isSelected = !currButton.isSelected

        if currButton.isSelected {
            currButton.backgroundColor = UIColor.darkGray
        } else {
            currButton.backgroundColor = UIColor.clear
        }
   }
}

Code above make the multiple selection but I need a single selection. I have read this and this but I am still stuck.

halfer
  • 19,824
  • 17
  • 99
  • 186
MrX
  • 953
  • 2
  • 16
  • 42
  • Do you mean to disable the selected buttons like if you press a button, it will be disabled while the others will be as normal? – Lawliet Jul 20 '17 at 03:26
  • @Lawliet My case its like single selection with checkmark in `UITableView`. Only One button can be highlight. If another button pressed, the last highlight button will be unhighlight. – MrX Jul 20 '17 at 03:33
  • @MarioMargoPradipta see my solution work for you – Jaydeep Vyas Jul 20 '17 at 03:37

4 Answers4

7

I think it is very easy just try it

@IBAction func onClickButton(_ sender: UIButton) {
    deselectAllButtons()
    sender.isSelected = true
}
func deselectAllButtons(){
    for subView in view.subviews 
      {
        // Set all the other buttons as normal state
        if let button = subView as? UIButton {
            button.isSelected = false
        }
    }
   //Or you can simply do write above for loop code with one line
  /*
   view.subviews.forEach { ($0 as? UIButton)?.isSelected = false }
  */
}
Jaydeep Vyas
  • 4,411
  • 1
  • 18
  • 44
  • Thanks for answer, but isSelected not make my button highlight, disable or etc – MrX Jul 20 '17 at 03:45
  • 1
    you can also use isEnabled,isHighlighted instead of isSelected – Jaydeep Vyas Jul 20 '17 at 03:46
  • Its work with `button.backgroundColor`. Why is `isHighlighted` not draw a highlight? – MrX Jul 20 '17 at 03:54
  • @MarioMargoPradipta you mean to say if user select any button once, he/she not able to select any other button also right – Jaydeep Vyas Jul 20 '17 at 04:05
  • Of course not. If user select one button, that button will highlight. But user can select another button, but when another button selected, the last highlight button wi be in normal state – MrX Jul 20 '17 at 04:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/149666/discussion-between-jaydeep-vyas-and-mario-margo-pradipta). – Jaydeep Vyas Jul 20 '17 at 04:08
  • @SPatel Please only suggest edits that change syntax if they either 1) correct a syntax mistake 2) or clearly improve the code, making it more readable or easy to understand. You're suggestion does the opposite of 2). – idmean Nov 02 '17 at 11:08
  • @idmean oky thanx Bhadme jao – SPatel Nov 02 '17 at 11:10
  • @idmean But You are wrong at "You're suggestion does the opposite of 2)" – SPatel Nov 02 '17 at 11:15
  • 1
    @SPatel Your code redundantly returns values and uses the same in Swift uncommon pattern of first checking and then casting. A more idiomatic way of writing your code would be `view.subviews.forEach { ($0 as? UIButton)?.isSelected = false } `. Still, there's no need to pack everything into one line. – idmean Nov 02 '17 at 11:21
  • I think now everything is ok. – Jaydeep Vyas Nov 02 '17 at 11:26
4

When the amount of buttons is large, what I would suggest is to instead keep track of the last selected button. On top of all your existing buttons create a

var lastSelectedButton: UIButton()

then in your buttonDisplayAction do something like

@IBAction func buttonDisplayAction(_ sender: UIButton) {

    lastSelectedButton.isSelected = false //Plus any deselect logic for this button
    lastSelectedButton = sender //If any buttons are not affect by this selection logic exclude them here
    sender.isSelected = true
    ...
}

This will work the same regardless of how many buttons you have.

Additionally you can use titleColor(for:) to change the color of your button for .selected state. The background color of your button for .selected state is by default the tintColor of the button.

Ben Ong
  • 913
  • 1
  • 10
  • 25
2

You can check all subViews as buttons in your view, unhighlight all of them and highlight the only selected button. In this case, I use backgroundColor as showing in your code sample.

     @IBAction func buttonDisplayAction(_ sender: UIButton) {
        // ...

        for subView in view.subviews {            
            // Set all the other buttons as normal state
            if let button: UIButton = subView as? UIButton {
                button.isHighlighted = false
            }
        }
        // Highlight the current selected
        sender.isHighlighted = true
    }

If you want your button background color changes after highlighting/unhighlighting and you intend to apply this for a bunch of buttons, you can override isHighlighted variable for the convenience.

extension UIButton {
    open override var isHighlighted: Bool {
        didSet {
            if isHighlighted {
                backgroundColor = .darkGray
            } else {
                backgroundColor = .clear
            }
        }
    }
}
Lawliet
  • 3,438
  • 2
  • 17
  • 28
1

1.### Multiple Buttons In Single Selection In swift4

   class SignUpStep1VC: UIViewController {

        @IBOutlet weak var btnPersonal: UIButton!
        @IBOutlet weak var btnPersonal1: UIButton!


        @IBOutlet weak var btnCompany: UIButton!
        @IBOutlet weak var btnICO: UIButton!


        @IBOutlet weak var btnCompany1: UIButton!
        @IBOutlet weak var btnICO1: UIButton!

        var strAccountType:String = "Personal"
        var ButtonsArr = [(btn:UIButton,text:String)]()

        override func viewDidLoad() {
            super.viewDidLoad()
            btnNext.layer.cornerRadius = 20
            btnPersonal.isSelected = true
            ButtonsArr.append((btn: btnPersonal, text: "Personal"))
            ButtonsArr.append((btn: btnICO, text: "ICO"))
            ButtonsArr.append((btn: btnCompany, text: "Company"))
            ButtonsArr.append((btn: btnPersonal1, text: "Personal"))
            ButtonsArr.append((btn: btnICO1, text: "ICO"))
            ButtonsArr.append((btn: btnCompany1, text: "Company"))
    }

   @IBAction func btnSelect_click(_ sender: UIButton) {

        ButtonsArr.forEach{
            $0.btn.isSelected = false
        }

        strAccountType = ButtonsArr[sender.tag].text
        ButtonsArr[sender.tag].btn.isSelected = true

    }

    }
  • 1
    I Have Six Buttons Every button I gave Tag and Sates In storyboard . And I have Create one ButtonsArr like This var ButtonsArr = [(btn:UIButton,text:String)]() and appending All buttons Into text into That ButtonsArr. when ever I can click the button By using ForEach All are false and after I get the Text And Selected Button true. – Praveen Reddy Oct 16 '19 at 06:02
  • 1
    Can u take outlet connection that time no need Create button Array.Thats Also work. – Praveen Reddy Oct 16 '19 at 06:30