Подтвердить что ты не робот

Swift: получить все подвидности определенного типа и добавить к массиву

У меня есть пользовательский класс кнопок в UIView, который я бы хотел добавить в массив, чтобы они были легко доступны. Есть ли способ получить все подъязыки определенного класса и добавить его в массив в Swift?

4b9b3361

Ответ 1

Функция filter, использующая оператор is, может фильтровать элементы определенного класса.

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

MyButtonClass - это настраиваемый класс для фильтрации.

Ответ 2

Здесь вы идете

    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
        }
    }

Вы можете называть его как

let allSubviews = view.allSubViewsOf(type: UIView.self)
let allLabels = view.allSubViewsOf(type: UILabel.self)

Ответ 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
}

Чтобы получить все UILabel в иерархии представлений, просто выполните следующее:

let allLabels : [UILabel] = getSubviewsOf(view: theView)

Ответ 4

Я не могу проверить это сейчас, но это должно работать в Swift 2:

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

Возвращает массив YourView

Здесь приведен пример типичного примера для получения счета:

countDots = allDots!.view.subviews.flatMap{$0 as? Dot}.count

Ответ 5

Если вы хотите обновить/получить доступ к этим конкретным подзаголовкам, используйте это,

for (index,button) in (view.subviews.filter{$0 is UIButton}).enumerated(){
    button.isHidden = false
}

Ответ 6

В Swift 4.1 вы можете использовать новый compactMap (flatMap теперь устарел): https://developer.apple.com/documentation/swift/sequence/2950916-compactmap (см. Примеры внутри)

В вашем случае вы можете использовать:

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

И вы можете выполнить действия для всех кнопок, используя карту:

let _ = stackView.subviews.compactMap{ $0 as? UIButton }.map { $0.isSelected = false }

Ответ 7

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)

Ответ 8

В этом случае, я думаю, мы могли бы использовать синтаксис Swift first.where, который более эффективен, чем filter.count, filter.isEmpty.

Потому что, когда мы используем filter, он создаст базовый массив, поэтому неэффективен, предположим, что у нас есть большая коллекция.

Итак, просто проверьте, содержит ли коллекция subViews определенный тип класса, мы можем использовать этот

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

который эквивалентен: найдите мне первое совпадение с классом BannerView в этом представлении subViews collection. Поэтому, если это так, мы можем выполнить нашу дальнейшую логику.

Ссылка: https://github.com/realm/SwiftLint/blob/master/Rules.md#first-where

Ответ 9

UIView имеет свойство с именем subViews, вы можете увидеть API.

Ответ 10

Позвольте мне опубликовать мой вариант этого) но это, находит первый из T

extension UIView {

    func firstSubView<T: UIView>(ofType type: T.Type) -> T? {
        var resultView: T?
        for view in subviews {
            if let view = view as? T {
                resultView = view
                break
            }
            else {
                if let foundView = view.firstSubView(ofType: T.self) {
                    resultView = foundView
                    break
                }
            }
        }
        return resultView
    }
}

Ответ 11

Так что многие ответы здесь излишне многословны или недостаточно общие. Вот как получить все подпредставления вида на любой глубине, которые относятся к любому желаемому классу:

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
    }
}

Как использовать:

let arr = myView.subviews(ofType: MyButtonClass.self)