ios - Swift: obtenga todas las subvistas de un tipo específico y agregue a una matriz
arrays class (9)
Aqui 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
}
}
Puedes llamarlo como
let allSubviews = view.allSubViewsOf(type: UIView.self)
let allLabels = view.allSubViewsOf(type: UILabel.self)
Tengo una clase personalizada de botones en una vista UIV que me gustaría agregar a una matriz para que sean fácilmente accesibles. ¿Hay alguna manera de obtener todas las subvistas de una clase específica y agregarlas a una matriz en Swift?
Desde Swift 4.1, puedes usar el nuevo mapa compacto (el mapa plano ahora está obsoleto): https://developer.apple.com/documentation/swift/sequence/2950916-compactmap (ver ejemplos dentro)
En su caso, puede utilizar:
let buttons:[UIButton] = stackView.subviews.compactMap{ $0 as? UIButton }
Y puedes ejecutar acciones a todos los botones usando el mapa:
let _ = stackView.subviews.compactMap{ $0 as? UIButton }.map { $0.isSelected = false }
No puedo probarlo ahora, pero esto debería funcionar en Swift 2:
view.subviews.flatMap{ $0 as? YourView }
Lo que devuelve una matriz de YourView
Aquí hay un ejemplo típico probado para obtener un conteo:
countDots = allDots!.view.subviews.flatMap{$0 as? Dot}.count
Para este caso, creo que podríamos usar la sintaxis de Swift''s first.where
, que es más eficiente que filter.count
, filter.isEmpty
.
Porque cuando usamos el filter
, creará una matriz subyacente, por lo tanto no es efectivo, imagina que tenemos una gran colección.
Así que simplemente compruebe si la colección de subViews
una vista contiene un tipo específico de clase, podemos usar este
let containsBannerViewKind = view.subviews.first(where: { $0 is BannerView }) != nil
lo que equivale a: encontrar la primera coincidencia con la clase BannerView en la colección de subvistas de esta vista. Entonces, si esto es cierto, podemos llevar a cabo nuestra lógica adicional.
Referencia: https://github.com/realm/SwiftLint/blob/master/Rules.md#first-where
Para hacer esto recursivamente (es decir, obtener todas las vistas de subvistas también), puede usar 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
}
Para obtener todos los UILabel en una jerarquía de vistas, simplemente haga esto:
let allLabels : [UILabel] = getSubviewsOf(view: theView)
Si desea actualizar / acceder a esas subvistas específicas, utilice esto,
for (index,button) in (view.subviews.filter{$0 is UIButton}).enumerated(){
button.isHidden = false
}
UIView tiene una propiedad llamada subViews
, puede ver la API.
La función de filter
que utiliza el operador is
puede filtrar elementos de una clase específica.
let myViews = view.subviews.filter{$0 is MyButtonClass}
MyButtonClass
es la clase personalizada para filtrar.
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)