How can I loop through all subviews of a UIView, and their subviews and their subviews

87,554

Solution 1

Use recursion:

// UIView+HierarchyLogging.h
@interface UIView (ViewHierarchyLogging)
- (void)logViewHierarchy;
@end

// UIView+HierarchyLogging.m
@implementation UIView (ViewHierarchyLogging)
- (void)logViewHierarchy
{
    NSLog(@"%@", self);
    for (UIView *subview in self.subviews)
    {
        [subview logViewHierarchy];
    }
}
@end

// In your implementation
[myView logViewHierarchy];

Solution 2

Well here is my solution using recursion and a wrapper(category/extension) for the UIView class.

// UIView+viewRecursion.h
@interface UIView (viewRecursion)
- (NSMutableArray*) allSubViews;
@end

// UIView+viewRecursion.m
@implementation UIView (viewRecursion)
- (NSMutableArray*)allSubViews
{
   NSMutableArray *arr=[[[NSMutableArray alloc] init] autorelease];
   [arr addObject:self];
   for (UIView *subview in self.subviews)
   {
     [arr addObjectsFromArray:(NSArray*)[subview allSubViews]];
   }
   return arr;
}
@end

Usage : Now you should be looping through all the sub views and manipulate them as needed.

//disable all text fields
for(UIView *v in [self.view allSubViews])
{
     if([v isKindOfClass:[UITextField class]])
     {
         ((UITextField*)v).enabled=NO;
     }
}

Solution 3

Here's another Swift implementation:

extension UIView {
    var allSubviews: [UIView] {
        return self.subviews.flatMap { [$0] + $0.allSubviews }
    }
}

Solution 4

A solution in Swift 3 that gives all subviews without including the view itself:

extension UIView {
var allSubViews : [UIView] {

        var array = [self.subviews].flatMap {$0}

        array.forEach { array.append(contentsOf: $0.allSubViews) }

        return array
    }
}

Solution 5

Just found an interesting way to do this through the debugger:

http://idevrecipes.com/2011/02/10/exploring-iphone-view-hierarchies/

references this Apple Technote:

https://developer.apple.com/library/content/technotes/tn2239/_index.html#SECUIKIT

Just make sure your debugger is paused (either set a break point of pause it manually) and you can ask for the recursiveDescription.

Share:
87,554
123hal321
Author by

123hal321

Updated on September 25, 2020

Comments

  • 123hal321
    123hal321 over 3 years

    How can I loop through all subviews of a UIView, and their subviews and their subviews?

  • ivanzoid
    ivanzoid almost 13 years
    Note there are memory leak in allSubViews function: you must either create array as [[[NSMutableArray alloc] init] autorelease] or as [NSMutableArray array] (which is the same).
  • docchang
    docchang over 12 years
    Is there a way to pass a function in the logViewHierarchy? That way it can suit your needs at different times.
  • Ole Begemann
    Ole Begemann over 12 years
    @docchang: Obj-C blocks are a great fit for that use case. You pass a block to the method, execute the block and pass it down the hierarchy with each method call.
  • Eric G
    Eric G almost 12 years
    Looks like I made a very similar solution as the one you proposed here. I went ahead and posted it on github in case others might find it useful. Here's my answer w/ the link :) stackoverflow.com/a/10440510/553394
  • Dimitris
    Dimitris almost 12 years
    By "a wrapper for UIView" you actually mean "a category for UIView".
  • RamaKrishna Chunduri
    RamaKrishna Chunduri almost 12 years
    Yes Dimitris, i meant category.
  • jaredsinclair
    jaredsinclair almost 11 years
    Nice. I posted a snippet below that adds whitespace indentation to this technique.
  • Admin
    Admin about 10 years
    How could I add a way to halt the recursion from within the block? Say I'm using this to locate a specific view, once I've found it I'd like to stop there and not continue searching the rest of the view hierarchy.
  • Ashish Ramani
    Ashish Ramani over 8 years
    helpful solution and time saver.. thanx 1 plus for u
  • Jed Fox
    Jed Fox over 7 years
    Please use the edit link explain how this code works and don't just give the code, as an explanation is more likely to help future readers. See also How to Answer. source
  • Jed Fox
    Jed Fox over 7 years
    Please see my comment above.
  • Rahul Patel
    Rahul Patel over 6 years
    What is need of ".flatMap {$0}" in this line "var array = [self.subviews].flatMap {$0}" ?
  • ielyamani
    ielyamani over 6 years
    @RahulPatel it removes nil elements from an array, for safety when calling allSubViews on subviews.
  • Balaji Ramakrishnan
    Balaji Ramakrishnan about 5 years
    Simple and Best one
  • SundialSoft
    SundialSoft over 4 years
    can you explain where the 'empty area' is ? I have tried all around the Xcode window once the breakpoint has fired but can't find where to input the string
  • Alexander Langer
    Alexander Langer almost 2 years
    Sexy code. Made my day