Roduck Nickes
Roduck Nickes

Reputation: 1021

Disable multiple buttons easy way?

Is there any easy way I can do this? Let's say I have 10 different buttons and a textbox.

@IBOutlet var button1: UIButton!
@IBOutlet var button2: UIButton!
@IBOutlet var button3: UIButton!
@IBOutlet var button4: UIButton!
@IBOutlet var button5: UIButton!
@IBOutlet var button6: UIButton!
@IBOutlet var button7: UIButton!
@IBOutlet var button8: UIButton!
@IBOutlet var button9: UIButton!
@IBOutlet var button10: UIButton!

If textBox.text is "bt1", i want only enable button1, and disable the rest, and if textbox.text is "bt2", i want to only enable button2, and disable the rest, and so on...

Upvotes: 0

Views: 1116

Answers (3)

dfrib
dfrib

Reputation: 73186

Note that you mustn't necessarily create an array of your buttons. As an alternative---given that these are all the buttons in your View Controller---you can make use of Mirror(reflecting: ...:

/* ViewController.swift */
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var button1: UIButton!
    @IBOutlet weak var button2: UIButton!
    @IBOutlet weak var button3: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        button1.enabled = true
        button2.enabled = true
        button3.enabled = true
        setEnableValueForAllButtons(false, exceptForButton: "button2")

        print(button1.enabled)
        print(button2.enabled)
        print(button3.enabled)

        /* button1.enabled = false
           button2.enabled = true
           button3.enabled = false */
    }

    func setEnableValueForAllButtons(toValue: Bool, exceptForButton: String) {
        let buttons = Mirror(reflecting: self).children.filter { $0.value is UIButton && ($0.label ?? "") != exceptForButton}
        for button in buttons {
            (button.value as? UIButton)?.enabled = toValue
        }
    }
}

If you want to only show the button whose property name is entered into a text field, you can simply extend the example above to include the text field, and call the setEnableValueForAllButtons(...) function from the UITextFieldDelegate method textFieldShouldReturn (hence after you press return after entering a string in the text field) as follows:

/* ViewController.swift */
import UIKit    
class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var button1: UIButton!
    @IBOutlet weak var button2: UIButton!
    @IBOutlet weak var button3: UIButton!        
    @IBOutlet weak var textBox: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        button1.enabled = false
        button2.enabled = false
        button3.enabled = false

        textBox.delegate = self
    }

    func setEnableValueForAllButtons(toValue toValue: Bool, exceptForButton: String) {
        let buttons = Mirror(reflecting: self).children.filter { $0.value is UIButton && ($0.label ?? "") != exceptForButton}
        for button in buttons {
            (button.value as? UIButton)?.enabled = toValue
        }
    }

     // UITextFieldDelegate
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()

        setEnableValueForAllButtons(toValue: true, exceptForButton: "")
        setEnableValueForAllButtons(toValue: false, exceptForButton: textField.text ?? "")

        return true
    }
}

If it's important for you to use triggers "bt1", "bt2" and so on, you could just rename the names of the button outlets to these values.

enter image description here

Upvotes: 1

Rich Tolley
Rich Tolley

Reputation: 3842

UPDATED:

As I understand it you want to enable/disable buttons depending on some text entered into a textField. I'm assuming you have a method which is called from one of the textField delegate methods. I'm also assuming that there is a 1 to 1 mapping from the text you enter to the buttons i.e that the user has to type exactly "btn1" - they can't do "button1" or "button 1" or any other variation. This is quite an odd requirement - are you sure this is what you really want?

First, as before put the buttons in an 'IBOutlet' collection:

 @IBOutlet var allButtons : [UIButton]!

Then, use an enumeration to map the textbox text to the index of the buttons in the collection

enum ButtonMapping : String {
  case button1 = "btn1"
  case button2 = "btn2"
//and so on

  func buttonIndex() -> Int {
    switch(self) {
        case button1: return 0
        case button2: return 1
        //and so on
    }
  }
}

Then just do something like:

func disableButtonsForText(text:String) {
  if let mapping = ButtonMapping(rawValue:text) {
    let activeButton = allButtons[mapping.buttonIndex]
      for button in allButtons {
        if button != activeButton {
          button.enabled = false
        }
      }
   } 
}

This will change the state of the buttons only when the let binding is successful - i.e. when the string supplied to the ButtonMapping constructor is a valid button name. In all other cases, the state of the buttons won't change. You might want to consider adding an else clause to reset the state of the buttons to normal if the text is not recognised - not sure what you want here.

Upvotes: 1

user4385051
user4385051

Reputation:

You can create an IBOutletCollection of UIButton.

And accessing them like that:

button[0].enabled = false

Iterate through the array to disable all button.

Upvotes: 1

Related Questions