问题
I've made a series of checkboxes in UiKit with UIButtons:
@IBOutlet weak var Box1: UIButton!
@IBOutlet weak var Box2: UIButton!
@IBOutlet weak var Box3: UIButton!
....
@IBOutlet weak var Box59: UIButton!
// Gives the button an action
@IBAction func Box1(_ sender: UIButton) {
    sender.isSelected = !sender.isSelected
}
@IBAction func Box2(_ sender: UIButton) {
    sender.isSelected = !sender.isSelected
}
@IBAction func Box3(_ sender: UIButton) {
    sender.isSelected = !sender.isSelected
}
    ....
@IBAction func Box59(_ sender: UIButton) {
    sender.isSelected = !sender.isSelected
}
// Creates button images of checkbox and unchecked box
var BoxON = UIImage(named: "CheckBox")
var BoxOFF = UIImage(named:"UnCheckBox")
// Allows the button to be set to the image, if selected or not 
override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    Box1.setImage(BoxOFF, for: .normal)
    Box1.setImage(BoxON, for: .selected)
    Box2.setImage(BoxOFF, for: .normal)
    Box2.setImage(BoxON, for: .selected)
    Box3.setImage(BoxOFF, for: .normal)
    Box3.setImage(BoxON, for: .selected)
    ....
    Box59.setImage(BoxOFF, for: .normal)
    Box59.setImage(BoxON, for: .selected)
    }
This is all the code necessary to make as many checkboxes as possible. However, each checkbox requires creating/moving a button to the right spot on the storyboard, linking the button from the storyboard to the button variable that was just coded. This can take a lot of time since I need over 100 buttons per view controller.
Is there a faster way to do this by making an array of buttons? or something similar?
回答1:
It is possible to declare an IBOutlet as array
Create an
IBOutletas array@IBOutlet var boxes : [UIButton]!Connect all buttons to the same outlet (in the desired order)
In
viewDidAppearuse a loop orforEachoverride func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) boxes.forEach { $0.setImage(BoxOFF, for: .normal) $0.setImage(BoxON, for: .selected) } }Add unique tags to the buttons (optional).
- Create one 
IBActionand connect all buttons to the action Use a switch statement to distinguish the buttons by index in the array or by tag
@IBAction func boxTouched(_ sender: UIButton) { sender.isSelected = !sender.isSelected let index = boxes.index(of: sender)! switch index { // handle the cases } } @IBAction func boxTouched(_ sender: UIButton) { sender.isSelected = !sender.isSelected switch sender.tag { // handle the cases } }
回答2:
I have created array of checkboxes(buttons) along with text(labels). You can select and deselect any button.
func addCheckBoxButtonsForSecondContainerView ()
{
    var xPosition = 0
    var yPosition = 0
    for i in 0..<likedArray.count
           {
               let secondViewCheckBox = UIButton(frame: CGRect(x: xPosition, y: yPosition, width: 18, height: 18))
               secondViewCheckBox.layer.borderWidth = 1
               secondViewCheckBox.layer.borderColor = UIColor(red: 1.0 / 255.0, green: 202.0 / 255.0, blue: 91.0 / 255.0, alpha: 1.0).cgColor
               secondViewCheckBox.addTarget(self, action: #selector(secondViewButtonAction(_:)), for: .touchUpInside)
               secondViewCheckBox.tag = i
               secondViewCheckBox.layer.cornerRadius = 2
               self.secondContainerView.addSubview(secondViewCheckBox)//adding button to container view
            //In the below line I'm creating label for title.
            let labelTitle = UILabel(frame: CGRect(x: xPosition+25, y: yPosition, width: 130, height: 18))  //UIButton(frame: CGRect(x: xPosition+30, y: yPosition, width: 100, height: 18))
            labelTitle.text = "  " + self.likedArray[i]
            labelTitle.font = UIFont.RummyLatoRegular(size: 12)
            labelTitle.tag = secondViewCheckBox.tag
            labelTitle.textAlignment = .left
            labelTitle.isUserInteractionEnabled = true
            labelTitle.textColor = UIColor.white
            labelTitle.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(secondViewLabelAction(_:))))
            self.secondContainerView.addSubview(labelTitle)//adding label to the containerview
            if i != 0 && (i+1)%3 == 0
            {
                xPosition = 0
                yPosition = Int(secondViewCheckBox.frame.origin.y+secondViewCheckBox.frame.size.height+15)
            }
            else
            {
                xPosition += 160
            }
           }
    
}
//Next we see here action for the buttons(checkboxes)
 @objc func secondViewButtonAction(_ sender: UIButton)
   {
    if arrayofSelectedIndexes.contains(sender.tag)
    {
        for i in 0..<arrayofSelectedIndexes.count
        {
            if arrayofSelectedIndexes[i] == sender.tag
            {
                arrayofSelectedIndexes.remove(at: i)
                sender.setBackgroundImage(UIImage.init(named: ""), for: .normal)
                break
            }
        }
    }
    else
    {
        arrayofSelectedIndexes.append(sender.tag)
        sender.setBackgroundImage(UIImage.init(named: "npsTickIcon"), for: .normal)
    }
}
//this is for title label action
 @objc func secondViewLabelAction(_ sender: UITapGestureRecognizer)
      {
        for subview in self.secondContainerView.subviews {
            if let button = subview as? UIButton {
                let searchlbl:UILabel = (sender.view as! UILabel) //just to get sender tag
                if searchlbl.tag == subview.tag
                {
                    if arrayofSelectedIndexes.contains(searchlbl.tag)
                    {
                        for i in 0..<arrayofSelectedIndexes.count
                        {
                            if arrayofSelectedIndexes[i] == searchlbl.tag
                            {
                                arrayofSelectedIndexes.remove(at: i)
                                button.setBackgroundImage(UIImage.init(named: ""), for: .normal)
                                break
                            }
                        }
                    }
                    else{
                        arrayofSelectedIndexes.append(searchlbl.tag)
                    button.setBackgroundImage(UIImage.init(named: "npsTickIcon"), for: .normal)
                    }
                }
                
            }
        }
Let me know if you need more clarification. User can click on button or title label. Same action will be performed. I'm attaching the screenshot here for output. [1]: https://i.stack.imgur.com/cXoww.png
来源:https://stackoverflow.com/questions/50068413/array-of-uibuttons-in-swift-4