如何获取UIView层次结构索引?(即在其他子视图之间的深度)

25

来自UIView文档:

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

我很高兴可以在特定索引处插入UIView,但我找不到一种方法来读取给定UIView的索引。

我需要检查UIView是否在顶部或底部...

2个回答

49
我几乎可以确定索引与subviews属性中的子视图的索引相同。
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

我刚刚用以下代码进行了测试,它有效

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

1
在发布问题之前,我刚试过这个。子视图数组中的索引保持不变 :( - Marin Todorov
你说得完全正确,Brandon。我有一个视图映射器,它不会改变索引;另一方面,子视图数组会改变它们。谢谢。然而,我必须承认文档对于如何获取索引以及较小的索引是在顶部还是反之的描述比较模糊。 - Marin Todorov
2
哈哈。是的,它们非常模糊,这就是为什么我在进行了大量测试之前不确定答案的原因。结果发现索引0是背面,索引(# of views - 1)是正面,并且数组保持正确的顺序。不过我还没有看到支持此说法的参考文档,所以希望它在以后的SDK中不会改变。 - user120587
Brandon,我整理了一个用于管理UIView深度的小类别,我在贡献说明中放了你网站的链接(原问题中有URL),请告诉我是否可以。 - Marin Todorov
2
它在UIView文档中。从subviews方法的Discussion部分,“数组中子视图的顺序反映了它们在屏幕上的可见顺序,索引为0的视图是最后面的视图。”所以不用担心它会很快改变。这是官方的。 - baudot
显示剩余2条评论

7

请设置一个递归方法,如下:

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

然后使用以下方式调用:

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

输出:

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

1
或者(未记录,但有效):NSLog(@“%@”,[self.view recursiveDescription]); - Mark Beaton
1
@MarkBeaton 我尝试这样做时出现了错误:'UIView'没有可见的@interface声明选择器'recursiveDescription'。 - aleclarson
1
这是一个私有方法 - 我通常只在调试器中使用它(例如po [someView recursiveDescription])。在代码中,您可以尝试[someView performSelector:@selector(recursiveDescription)]来避免编译器错误,或者简单地(暂时)禁用该编译器错误。 - Mark Beaton
@MarkBeaton,如果我在调试某些视图时知道了这个,那该有多好啊...谢谢!你是怎么发现它的? - Iulian Onofrei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接