Swift: Obtener todas las subvistas de un tipo específico y añadir a una matriz

Tengo una clase personalizada de botones en un UIView que me gustaría añadir a una matriz de forma que sean fácilmente accesibles. Es allí una manera de conseguir todas las subvistas de una clase específica y agregarlo a una matriz en Swift?

  • tenga cuidado de fuera de la fecha de respuestas aquí, desplácese hasta la parte inferior

10 Kommentare

  1. 69

    La filter función utilizando el is operador puede filtrar los elementos de una clase específica.

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

    MyButtonClass es la clase personalizada para filtrar.

    • Esto funcionó, pero con una sintaxis un poco off: se Debe dejar myViews = vista.subvistas.filtro({$0 es MyButtonClass})
    • La sintaxis es la llamada «Trailing» Cierre symtax: If a closure expression is provided as the function’s only argument and you provide that expression as a trailing closure, you do not need to write a pair of parentheses () after the function’s name when you call the function.
    • Tengo curiosidad por ver si hay una manera para que este método de conexión en cadena
    • Parece que no se puede utilizar al final de cierre si se llama a un objeto que aparece después de «en» en un «en» loop: para myButton a la vista.subvistas.filtro{$0 es MyButtonClass} { } ha de error: «Anónimo cierre argumento de que no esté contenida en un cierre»
    • top respuesta!!
    • Esta solución no es recursiva, sólo listas directa subvistas.
    • A la derecha, la cuestión no se menciona la la recursividad.

  2. 29

    Aquí tienes

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

    Se le puede llamar como

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

    Para hacer esto de forma recursiva (I. e. buscar todos los subvista opiniones así), puede utilizar esta función genérica:

    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
    }

    Buscar todos los UILabel en una jerarquía, basta con hacer:

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

    Yo no puedo probarlo ahora mismo, pero esto debería funcionar en Swift 2:

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

    Que devuelve una matriz de YourView

    He aquí una prueba, típico ejemplo, para obtener un recuento:

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

    Si quieres actualizar/acceso a aquellos específicos de subvistas, a continuación, utilizar este,

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

    De Swift 4.1, puede utilizar la nueva compactMap (flatMap es ahora depcrecated): https://developer.apple.com/documentation/swift/sequence/2950916-compactmap
    (ver ejemplos en el interior)

    En su caso, usted puede utilizar:

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

    Y que se pueden ejecutar acciones a todos los botones y uso mapa:

    let _ = stackView.subviews.compactMap{ $0 as? UIButton }.map { $0.isSelected = false }
  7. 3
    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)
    • usted no es exactamente que responder el OP pregunta. Su func debe devolver una matriz de puntos de vista, ya que eso es lo que el OP se le solicita; y por qué UITextField? MyCustomButton sería más apropiado.
  8. 2

    Para este caso, creo que podríamos utilizar Swift first.where la sintaxis, la cual es más eficiente que filter.count, filter.isEmpty.

    Porque cuando utilizamos filter, va a crear una matriz subyacente, por lo tanto no es eficaz, imaginemos que tenemos una gran colección.

    Lo acaba de comprobar si una vista de la subViews colección contiene un tipo específico de clase, podemos usar este

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

    que equivalen a: me encontrarás en el primer partido a BannerView clase en esta vista de la subvistas colección. Así que si esto es cierto, podemos llevar a cabo nuestros más lógica.

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

  9. 2

    Muchas de las respuestas aquí son innecesariamente detallado o insuficientemente general. Aquí es cómo conseguir todas las subvistas de un punto de vista, en cualquier profundidad, que son de cualquier clase deseada:

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

    Cómo utilizar:

    let arr = myView.subviews(ofType: MyButtonClass.self)
    • Maravilloso! Muchas gracias!
  10. 0

    Me deja publicar mi variación de esto), pero este, se encuentra la primera de 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
        }
    }

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein