Swift:递归遍历所有子视图以查找特定类并附加到数组

Ken*_*and 20 arrays recursion uiview swift

有一段时间的魔鬼试图解决这个问题.我在这里问了一个类似的问题:Swift:获取特定类型的所有子视图并添加到数组中

虽然这有效,但我意识到有很多子视图和子视图,因此我需要一个从主UIView开始的函数,循环遍历所有子视图(及其子视图,直到没有任何左视图)并将其添加到一个自定义按钮类的数组,我将其命名为CheckCircle.

基本上我想最终得到一个CheckCircles数组,它构成了以编程方式添加到该视图的所有CheckCircles.

有任何想法吗?这就是我一直在努力的方面.它似乎没有将任何Checkcircles附加到数组:

    func getSubviewsOfView(v:UIView) -> [CheckCircle] {
        var circleArray = [CheckCircle]()
        // Get the subviews of the view

        var subviews = v.subviews

        if subviews.count == 0 {
            return circleArray
        }

        for subview : AnyObject in subviews{
  if let viewToAppend = subview as? CheckCircle {
        circleArray.append(viewToAppend as CheckCircle)
      }
            getSubviewsOfView(subview as! UIView)
        }
        return circleArray
    }
Run Code Online (Sandbox Code Playgroud)

Aar*_*ger 24

你的主要问题是,当你getSubviewsOfView(subview as! UIView)在函数内递归调用时,你没有对结果做任何事情.

您也可以删除count == 0检查,因为在这种情况下,for…in只会跳过循环.你还有一堆不必要的演员阵容

假设您希望获得一系列CheckCircle实例,我认为您的代码适应性应该有效:

func getSubviewsOfView(v:UIView) -> [CheckCircle] {
    var circleArray = [CheckCircle]()

    for subview in v.subviews as! [UIView] {
        circleArray += getSubviewsOfView(subview)

        if subview is CheckCircle {
            circleArray.append(subview as! CheckCircle)
        }
    }

    return circleArray
}
Run Code Online (Sandbox Code Playgroud)


Vas*_*huk 23

基于Aaron Bragerullstrm的回答

细节

Swift 4,Xcode 9.1

extension UIView {

    class func getAllSubviews<T: UIView>(from parenView: UIView) -> [T] {
        return parenView.subviews.flatMap { subView -> [T] in
            var result = getAllSubviews(from: subView) as [T]
            if let view = subView as? T { result.append(view) }
            return result
        }
    }

    class func getAllSubviews(from parenView: UIView, types: [UIView.Type]) -> [UIView] {
        return parenView.subviews.flatMap { subView -> [UIView] in
            var result = getAllSubviews(from: subView) as [UIView]
            for type in types {
                if subView.classForCoder == type {
                    result.append(subView)
                    return result
                }
            }
            return result
        }
    }

    func getAllSubviews<T: UIView>() -> [T] { return UIView.getAllSubviews(from: self) as [T] }
    func get<T: UIView>(all type: T.Type) -> [T] { return UIView.getAllSubviews(from: self) as [T] }
    func get(all types: [UIView.Type]) -> [UIView] { return UIView.getAllSubviews(from: self, types: types) }
}
Run Code Online (Sandbox Code Playgroud)

用法

var allViews = UIView.getAllSubviews(from: simpleView)
func printResult(with text: String) {
    print("\n==============================================")
    print("\(text):\n\(allViews.map { $0.classForCoder } )")
}
printResult(with: "UIView.getAllSubviews(from: simpleView)")

allViews = UIView.getAllSubviews(from: simpleView) as [UILabel]
printResult(with: "UIView.getAllSubviews(from: simpleView) as [UILabel]")

allViews = UIView.getAllSubviews(from: simpleView, types: [UIStackView.self, UILabel.self])
printResult(with: "UIView.getAllSubviews(from: simpleView, types: [UIStackView.self, UILabel.self])")

allViews = simpleView.getAllSubviews()
printResult(with: "simpleView.getAllSubviews()")

allViews = simpleView.getAllSubviews() as [UILabel]
printResult(with: "simpleView.getAllSubviews() as [UILabel]")

allViews = simpleView.get(all: UILabel.self)
printResult(with: "simpleView.get(all: UILabel.self)")

allViews = simpleView.get(all: [UIStackView.self, UILabel.self])
printResult(with: "simpleView.get(all: [UIStackView.self, UILabel.self])")
Run Code Online (Sandbox Code Playgroud)


ull*_*trm 16

我使用swift 3和泛型的方法!

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
}
Run Code Online (Sandbox Code Playgroud)

要获取视图层次结构中的所有UILabel,只需执行以下操作:

let allLabels: [UILabel] = getSubviewsOf(view: theView)
Run Code Online (Sandbox Code Playgroud)


sht*_*kgm 8

您可以通过扩展UIView并定义以下功能来简单地实现它。

Swift4代码

extension UIView {
    func findViews<T: UIView>(subclassOf: T.Type) -> [T] {
        return recursiveSubviews.compactMap { $0 as? T }
    }

    var recursiveSubviews: [UIView] {
        return subviews + subviews.flatMap { $0.recursiveSubviews }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

findViews(subclassOf: UILabel.self)
findViews(subclassOf: CheckCircle.self)
Run Code Online (Sandbox Code Playgroud)