25

From UIView docs:

(void)insertSubview:(UIView *)view atIndex:(NSInteger)index

It's great that I can insert a UIView at a certain index, but I cannot find a way to READ what index a given UIView has.

I need to check whether the UIView is on top, or at the back ...

benzado
  • 82,288
  • 22
  • 110
  • 138
Marin Todorov
  • 6,377
  • 9
  • 45
  • 73

2 Answers2

49

I am almost 100% sure that the index is the same as the index of the subView inside the superViews subviews property.

UIView * superView = .... some view
UIView * subView = .... some other view
[superView insertSubview:subView atIndex:index];
int viewIndex = [[superView subviews] indexOfObject:subView];
// viewIndex and index should be the same

I just tested this with the following code and it works

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
UIView* view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
UIView* view3 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[self.view insertSubview:view1 atIndex:1];
[self.view insertSubview:view2 atIndex:2];
[self.view insertSubview:view3 atIndex:3];

NSLog(@"%d", [[self.view subviews] indexOfObject:view1]); // Is 1
NSLog(@"%d", [[self.view subviews] indexOfObject:view2]); // Is 2
NSLog(@"%d", [[self.view subviews] indexOfObject:view3]); // Is 3

[self.view bringSubviewToFront:view1];
NSLog(@"%d", [[self.view subviews] indexOfObject:view1]); // Is end of array

[self.view sendSubviewToBack:view1];
NSLog(@"%d", [[self.view subviews] indexOfObject:view1]); // Is 0
Brandon Bodnar
  • 8,202
  • 2
  • 36
  • 42
  • 1
    I was trying out this just before posting the question. The indexes in the subviews array stay the same :( – Marin Todorov Feb 26 '10 at 17:27
  • Really, cause my test show that the index in the subview array does change after a call to `bringSubviewToFront:` – Brandon Bodnar Feb 26 '10 at 17:30
  • You are perfectly correct Brandon, I have a view mapper which doesn't change the indexes; the subviews array on the other hand changes them. Thanks. However I should admit the docs are vague on how to get the index and whether the smaller indexes are on top or vice versa. – Marin Todorov Feb 26 '10 at 18:15
  • 2
    Haha. Yup, they are very vague, that is why I was not sure of the answer till I did a bunch of test. Turns out index 0 is back, index (# of views - 1) is the front, and the array is kept in proper order. I haven't see a reference document to support this though, so I hope that it does not change in later SDKs – Brandon Bodnar Feb 26 '10 at 18:23
  • Brandon, I put together a small category for managing the UIView's depth, I put a link to your site as attribution (url in the original question now) let me know if ok with u – Marin Todorov Feb 26 '10 at 22:29
  • Sure. I treat most of what I do as creative commons. no problem here, but thanks for asking. Thanks for making the category available to others. – Brandon Bodnar Feb 26 '10 at 23:06
  • 2
    It's in the UIView documentation. From the Discussion section of the subviews method, "The order of the subviews in the array reflects their visible order on the screen, with the view at index 0 being the back-most view." So no worries of it changing anytime soon. It's official. – baudot Feb 14 '12 at 16:25
7

Set up a recursive method as follows:

- (void)printViewHierarchy:(UIView *)viewNode depth:(NSUInteger)depth
{
    for (UIView *v in viewNode.subviews)
    {
        NSLog(@"%@%@", [@"" stringByPaddingToLength:depth withString:@"|-" startingAtIndex:0], [v description]);
        if ([v.subviews count])
            [self printViewHierarchy:v depth:(depth + 2)]; // + 2 to make the output look correct with the stringPadding
    }
}

Then call it with:

[self printViewHierarchy:self.view depth:0];

Output:

[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: <UILayoutContainerView: 0x622ce70; frame = (0 0; 768 1004); autoresize = W+H; layer = <CALayer: 0x622cec0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-<UINavigationTransitionView: 0x622cfa0; frame = (0 0; 768 1004); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x622cff0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-<UIViewControllerWrapperView: 0x601c4c0; frame = (0 0; 768 1004); autoresize = RM+BM; layer = <CALayer: 0x607c5f0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-<UIView: 0x6069c40; frame = (0 0; 768 1004); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x607b460>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-<UIToolbar: 0x623a550; frame = (0 0; 768 44); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x623a610>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-<UIToolbarTextButton: 0x626d6a0; frame = (7 0; 52 44); opaque = NO; layer = <CALayer: 0x626e200>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIPushButton: 0x626d920; frame = (0 7; 52 30); opaque = NO; layer = <CALayer: 0x626d9c0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-<UIView: 0x623a440; frame = (69 -1; 755 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x623a470>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIButton: 0x621cec0; frame = (-185 0; 505 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x621cc20>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x62206d0; frame = (-35 -28; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x621cc50>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x607ec40; frame = (0 7; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x607ec70>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIButtonLabel: 0x62306c0; frame = (32 14; 38 16); text = 'About'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6230780>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIButton: 0x6230a00; frame = (-109 0; 510 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x6230660>>

[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x6230a90; frame = (-35 -28; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x6230ac0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x607ebc0; frame = (0 7; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x607ebf0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIButtonLabel: 0x6231620; frame = (35 14; 30 16); text = 'Staff'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6231e20>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIButton: 0x6231ea0; frame = (13 0; 465 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x6231e50>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x6231f30; frame = (-35 -28; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x6231f60>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x607eb40; frame = (0 7; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x607eb70>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIButtonLabel: 0x6233430; frame = (35 14; 71 16); text = 'Procedures'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x62334a0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIButton: 0x6233520; frame = (110 0; 485 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x62334d0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x62335b0; frame = (-35 -28; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x62335e0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x607eac0; frame = (0 7; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x607eaf0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIButtonLabel: 0x6234190; frame = (35 14; 52 16); text = 'Specials'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x62349d0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIButton: 0x6237560; frame = (200 0; 490 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x6237510>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x62375f0; frame = (-35 -28; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x6237620>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x607ea20; frame = (0 7; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x607ea50>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIButtonLabel: 0x6238170; frame = (35 14; 46 16); text = 'Gallery'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x62389d0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIButton: 0x6234a50; frame = (305 0; 475 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x6234a00>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x6234ae0; frame = (-35 -28; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x6234b10>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x607e940; frame = (0 7; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x607e970>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIButtonLabel: 0x6235670; frame = (35 14; 64 16); text = 'Education'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6235ed0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIButton: 0x6235f30; frame = (435 0; 455 45); opaque = NO; autoresize = W+BM; layer = <CALayer: 0x6235f00>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x6235fc0; frame = (-35 -28; 100 100); alpha = 0; opaque = NO; userInteractionEnabled = NO; tag = 1886548836; layer = <CALayer: 0x6235ff0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x607e7b0; frame = (0 7; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x607e7e0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIButtonLabel: 0x6236b80; frame = (35 14; 83 16); text = 'Appointment'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x6236bf0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-<UIView: 0x623a370; frame = (0 0; 768 1004); hidden = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x623a3a0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-<UIView: 0x6239f40; frame = (234 427; 300 150); autoresize = LM+RM+TM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x6239f70>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UILabel: 0x6239fa0; frame = (0 20; 300 22); text = 'Loading...'; clipsToBounds = YES; opaque = NO; autoresize = W+BM; userInteractionEnabled = NO; layer = <CALayer: 0x623a010>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UILabel: 0x623a120; frame = (0 40; 300 35); text = 'This may take a few minut...'; clipsToBounds = YES; opaque = NO; autoresize = W+BM; userInteractionEnabled = NO; layer = <CALayer: 0x623a190>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIActivityIndicatorView: 0x6238a70; frame = (132 93; 37 37); opaque = NO; autoresize = LM+RM+TM+BM; animations = { contents=<CAKeyframeAnimation: 0x605f810>; }; layer = <CALayer: 0x6238ad0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-<UIView: 0x62307e0; frame = (54 68; 660 916); hidden = YES; autoresize = LM+RM+H; layer = <CALayer: 0x6230810>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-<UIImageView: 0x6230840; frame = (0 0; 660 916); alpha = 0.75; hidden = YES; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x6230870>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-<UIPageControl: 0x621b7b0; frame = (0 887; 660 36); opaque = NO; autoresize = W+TM; layer = <CALayer: 0x621b870>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIImageView: 0x621ed20; frame = (279 15; 6 6); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x62215a0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIImageView: 0x621a620; frame = (295 15; 6 6); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x621b5c0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIImageView: 0x622d210; frame = (311 15; 6 6); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x621ca40>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIImageView: 0x621ca70; frame = (327 15; 6 6); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x621caa0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIImageView: 0x621cad0; frame = (343 15; 6 6); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x621cb00>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIImageView: 0x621cb30; frame = (359 15; 6 6); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x621cb60>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIImageView: 0x6226910; frame = (375 15; 6 6); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x621ed50>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-<UIScrollView: 0x623e9a0; frame = (0 0; 660 896); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x623c520>; contentOffset: {0, 0}>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-<UIView: 0x6248070; frame = (0 0; 660 896); autoresize = W+H; layer = <CALayer: 0x62480a0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UILabel: 0x62480d0; frame = (0 0; 660 35); text = 'About Us'; clipsToBounds = YES; opaque = NO; autoresize = W+BM; userInteractionEnabled = NO; layer = <CALayer: 0x6248140>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UIImageView: 0x621f280; frame = (0 50; 660 200); hidden = YES; autoresize = W+BM; userInteractionEnabled = NO; layer = <CALayer: 0x623bc70>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-<UITextView: 0x621db30; frame = (20 35; 620 646); text = ''; clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x6237ce0>; contentOffset: {0, 0}>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-|-<UITextSelectionView: 0x6232840; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x62328e0>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-|-<UIImageView: 0x6012950; frame = (615 266; 5 124); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x6069b90>>
[Line: 472] -[iPadRootViewController printViewHierarchy:depth:]: |-|-|-|-|-|-|-|-<UIWebDocumentView: 0x6a65e00; frame = (0 0; 620 50); text = ''; opaque = NO; userInteractionEnabled = NO; layer = <UIWebLayer: 0x6236980>>
chown
  • 51,908
  • 16
  • 134
  • 170
  • 1
    Or (undocumented, but works): NSLog(@"%@", [self.view recursiveDescription]); – Mark Beaton Mar 03 '13 at 07:07
  • 1
    @MarkBeaton `No visible @interface for 'UIView' declares the selector 'recursiveDescription'` I got this error trying to do that. – aleclarson Feb 27 '14 at 00:54
  • 1
    It's a private method - I usually only really use it in the debugger (e.g. ```po [someView recursiveDescription]```. In code, you could try ```[someView performSelector:@selector(recursiveDescription)]``` to avoid the compiler error, or simply (temporarily) disable that compiler error. – Mark Beaton Feb 27 '14 at 05:26
  • @MarkBeaton, If only I knew this when debugging some views ... Thanks! How did you found it? – Iulian Onofrei Apr 15 '15 at 11:00