2015-08-22 15 views

Odpowiedz

33

Funkcja filter przy użyciu operatora is może filtrować elementy określonej klasy.

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

MyButtonClass jest klasa zwyczaj być filtrowana.

+1

To działało, ale składnia była trochę wyłączona: Powinien być dozwolony myViews = view.subViews.filter ({$ 0 to MyButtonClass}) –

+3

Składnia jest nazywana symtektem "Trailing Closure": * 'Jeśli wyrażenie zamknięcia jest podane jako jedyny argument funkcji i podajesz to wyrażenie jako końcowe zamknięcie, nie musisz pisać pary nawiasów() po nazwie funkcji, gdy wywołujesz funkcję "* – vadian

+0

Jestem ciekawy, czy istnieje sposób na uczynienie tej metody łańcuchem – Trip

1

UIView ma właściwość o nazwie subViews, można zobaczyć interfejs API.

+0

Trzeba napisać tak: view.subviews.flatMap {$ 0 jak? YourView} – Maybe1

10

nie mogę przetestować go już teraz, ale to powinno działać w Swift 2:

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

Które zwraca tablicę YourView

Oto sprawdzony, typowy przykład, aby uzyskać count:

3

Jeśli chcesz zaktualizować/dostęp do tych konkretnych subviews następnie użyć tego,

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

Aby to zrobić rekursywnie (Ie pobierania widokami podrzędny za aswell), można użyć tego rodzajowego funkcję:

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 
} 

pobrać wszystkie UILabel w hierarchii widoku, po prostu to zrobić:

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

Tu idziesz

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

można nazwać jak

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

W tym przypadku, myślę, że możemy korzystać Swift first.where składni, który jest bardziej wydajny niż filter.count, filter.isEmpty.

Ponieważ gdy użyjemy filter, stworzy on podstawową tablicę, więc nie będzie skuteczna, wyobraźmy sobie, że mamy dużą kolekcję.

Więc po prostu sprawdzić, czy rzutem za subViews kolekcja zawiera specyficzny rodzaj klasy, możemy użyć tego

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

których równoważna: znajdź mnie pierwszy mecz klasy BannerView w tym widoku za subviews kolekcji. Jeśli to prawda, możemy przeprowadzić naszą dalszą logikę.

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

0
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

nie odpowiadasz dokładnie na pytanie OP. Twój 'func' powinien zwrócić tablicę widoków, ponieważ to właśnie zadał OP; i dlaczego "UITextField"? "MyCustomButton" byłoby bardziej odpowiednie. – dirkgroten

Powiązane problemy