24

How would I loop through all UIButtons in my view in Swift? I would want to set all the titles to "", but my for-loop in Swift is giving an error.

for btns in self.view as [UIButton] {
  // set the title to ""
}
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
melwyn pawar
  • 1,766
  • 2
  • 16
  • 21

9 Answers9

45

This code should work:

for view in self.view.subviews as [UIView] {
    if let btn = view as? UIButton {
        btn.setTitleForAllStates("")
    }
}

You need to iterate through the subViews array.

Benno Kress
  • 2,637
  • 27
  • 39
Woodstock
  • 22,184
  • 15
  • 80
  • 118
29

Shortened and updated for Swift 3 & 4

for case let button as UIButton in self.view.subviews {
    button.setTitleForAllStates("")
}
Benno Kress
  • 2,637
  • 27
  • 39
3

Looping over subview works, but it's sometimes a little ugly, and has other issues.

If you need to loop over some specific buttons, for example to add corner radius or change tint or background color, you can use an array of IBOutlets and then loop over that.

var buttons = [SkipBtn, AllowBtn]
for button in buttons as! [UIButton] {
    button.layer.cornerRadius = 5
}
afterxleep
  • 622
  • 1
  • 5
  • 17
1

Swift 4:

let subviewButtons = self.view.subviews.filter({$0.isKind(of: UIButton.self)})

for button in subviewButtons {
    //do something        
}
Jochen Holzer
  • 1,598
  • 19
  • 25
  • So I am using this for NSTextFields in a loop like in your answer, but in my loop I have `print(textField.identifier.rawValue)` and it is printing things like `_NS:9` as well the actual identifier I assigned in Storyboard. Why? I've not used any identifiers with those kinds of designations. – SouthernYankee65 Mar 23 '22 at 20:36
1

To add some context for a common use case, suppose the buttons were in a scroll view and you wanted to highlight the tapped button and de-highlight the other buttons. In this situation, you would direct all buttons to one action method:

@objc private func buttonAction(_ button: UIButton) {
    for case let b as UIButton in view.scrollView.subviews {
        if b == button {
            b.setTitleColor(UIColor.green, for: []) // highlight
        } else {
            b.setTitleColor(UIColor.black, for: []) // de-highlight
        }
    }
}
trndjc
  • 11,654
  • 3
  • 38
  • 51
0

This code seems to be quite useful for iterating over any object within a view, just change UIButton for any other subview type such as UIView or UIImageView, etc.

let filteredSubviews = self.view.subviews.filter({
    $0.isKindOfClass(UIButton)})

for view in filteredSubviews {
    //Do something        
}
Nando P.
  • 27
  • 8
0

Used some of the offered questions out there and created my own. I believe is the most efficient when you want to programmatically set up the title of various UIButtons(in my case I am building a quiz)

By randomising my array list and with just a for loop I printing the item at index to the button title

for view in self.viewForButtons.subviews{
        if view.isKindOfClass(UIButton)
        {
            let button : UIButton = view as! UIButton
            button.setTitle("item[i]", forState: .Normal)
        }
    }
cmario
  • 605
  • 1
  • 7
  • 22
0

If you have UIView's within self.view then you need to loop through the subviews while searching for UIButton. Using the accepted answer, I made this little function to do so:

Swift 4 + :

func findButton(`in` view: UIView){
    for view in view.subviews as [UIView] {
        if let button = view as? UIButton {
            // Do something with 'button'
        }else{
            // Loop through subview looking for buttons
            findButton(in: view)
        }
    }
}

Usage:

override func viewDidLoad() {
    findButton(in: self.view)
}

Hope this helps!

Matthew Mitchell
  • 514
  • 4
  • 14
-6

Here's a short way in Swift if you know the subview only has buttons:

myView.subviews.map {
  ($0 as? UIButton)!.enabled = false
}
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
Linh
  • 1