Swift: Get all subviews of a specific type and add to an array

后端 未结 11 712
Happy的楠姐
Happy的楠姐 2020-12-13 12:25

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

相关标签:
11条回答
  • 2020-12-13 12:55

    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

    0 讨论(0)
  • 2020-12-13 12:57

    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.

    To filter and cast the view to the custom type use compactMap

    let myViews = view.subviews.compactMap{$0 as? MyButtonClass}
    
    0 讨论(0)
  • 2020-12-13 13:00

    Here you go

        extension UIView {
    
        /** This is the function to get subViews of a view of a particular type 
    */
        func subViews<T : UIView>(type : T.Type) -> [T]{
            var all = [T]()
            for view in self.subviews {
                if let aView = view as? T{
                    all.append(aView)
                }
            }
            return all
        }
    
    
    /** This is a function to get subViews of a particular type from view recursively. It would look recursively in all subviews and return back the subviews of the type T */
            func allSubViewsOf<T : UIView>(type : T.Type) -> [T]{
                var all = [T]()
                func getSubview(view: UIView) {
                    if let aView = view as? T{
                    all.append(aView)
                    }
                    guard view.subviews.count>0 else { return }
                    view.subviews.forEach{ getSubview(view: $0) }
                }
                getSubview(view: self)
                return all
            }
        }
    

    You can call it like

    let allSubviews = view.allSubViewsOf(type: UIView.self)
    let allLabels = view.allSubViewsOf(type: UILabel.self)
    
    0 讨论(0)
  • 2020-12-13 13:00
    func allSubViews(views: [UIView]) {
        for view in views {
            if let tf = view as? UITextField {
                 // Do Something
            }
            self.allSubViews(views: view.subviews)
        }
    }
    
    self.allSubViews(views: self.view.subviews)
    
    0 讨论(0)
  • 2020-12-13 13:02

    So many of the answers here are unnecessarily verbose or insufficiently general. Here's how to get all subviews of a view, at any depth, that are of any desired class:

    extension UIView {
        func subviews<T:UIView>(ofType WhatType:T.Type) -> [T] {
            var result = self.subviews.compactMap {$0 as? T}
            for sub in self.subviews {
                result.append(contentsOf: sub.subviews(ofType:WhatType))
            }
            return result
        }
    }
    

    How to use:

    let arr = myView.subviews(ofType: MyButtonClass.self)
    
    0 讨论(0)
提交回复
热议问题