Swift: Get all subviews of a specific type and add

2020-02-17 06:24发布

I have a custom class of buttons in a UIView that I'd like to add to an array so that they're easily accessible. Is there a way to get all subviews of a specific class and add it to an array in Swift?

10条回答
叛逆
2楼-- · 2020-02-17 06:44

I can't test it right now but this should work in Swift 2:

view.subviews.flatMap{ $0 as? YourView }

Which returns an array of YourView

Here's a tested, typical example, to get a count:

countDots = allDots!.view.subviews.flatMap{$0 as? Dot}.count
查看更多
Emotional °昔
3楼-- · 2020-02-17 06:45

The filter function using the is operator can filter items of a specific class.

let myViews = view.subviews.filter{$0 is MyButtonClass}

MyButtonClass is the custom class to be filtered for.

查看更多
Bombasti
4楼-- · 2020-02-17 06:48

For this case, I think we could use Swift's first.where syntax, which is more efficient than filter.count, filter.isEmpty.

Because when we use filter, it will create a underlying array, thus not effective, imagine we have a large collection.

So just check if a view's subViews collection contains a specific kind of class, we can use this

let containsBannerViewKind = view.subviews.first(where: { $0 is BannerView }) != nil

which equivalent to: find me the first match to BannerView class in this view's subViews collection. So if this is true, we can carry out our further logic.

Reference: https://github.com/realm/SwiftLint/blob/master/Rules.md#first-where

查看更多
ゆ 、 Hurt°
5楼-- · 2020-02-17 06:52

From Swift 4.1, you can use new compactMap (flatMap is now depcrecated): https://developer.apple.com/documentation/swift/sequence/2950916-compactmap (see examples inside)

In your case, you can use:

let buttons:[UIButton] = stackView.subviews.compactMap{ $0 as? UIButton }

And you can execute actions to all buttons using map:

let _ = stackView.subviews.compactMap{ $0 as? UIButton }.map { $0.isSelected = false }
查看更多
Juvenile、少年°
6楼-- · 2020-02-17 06:53

To do this recursively (I.e. fetching all subview's views aswell), you can use this generic function:

private func getSubviewsOf<T : UIView>(view:UIView) -> [T] {
    var subviews = [T]()

    for subview in view.subviews {
        subviews += getSubviewsOf(view: subview) as [T]

        if let subview = subview as? T {
            subviews.append(subview)
        }
    }

    return subviews
}

To fetch all UILabel's in a view hierarchy, just do this:

let allLabels : [UILabel] = getSubviewsOf(view: theView)
查看更多
劫难
7楼-- · 2020-02-17 06:53

If you want to update/access those specific subviews then use this,

for (index,button) in (view.subviews.filter{$0 is UIButton}).enumerated(){
    button.isHidden = false
}
查看更多
登录 后发表回答