如何循环遍历一个UIView的所有子视图,以及它们的子视图和它们的子视图

87

我该如何循环遍历UIView的所有子视图、它们的子视图和它们的子视图?


7
如果你真的需要循环遍历,则接受的答案是正确的;如果只是寻找单个视图,则给它打标签并使用 viewWithTag,这样可以避免一些麻烦!- http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW26 - Norman H
18个回答

3
顺便说一下,我创建了一个开源项目来帮助完成这种任务。它非常容易使用,使用Objective-C 2.0块在层次结构中执行代码的所有视图。

https://github.com/egold/UIViewRecursion

例如:

-(void)makeAllSubviewsGreen
{
    [self.view runBlockOnAllSubviews:^(UIView *view) {

        view.backgroundColor = [UIColor greenColor];
    }];
}

2
这是对上面Ole Begemann的答案的一种变化,它添加了缩进以说明层次结构:
// UIView+HierarchyLogging.h
@interface UIView (ViewHierarchyLogging)
- (void)logViewHierarchy:(NSString *)whiteSpaces;
@end

// UIView+HierarchyLogging.m
@implementation UIView (ViewHierarchyLogging)
- (void)logViewHierarchy:(NSString *)whiteSpaces {
    if (whiteSpaces == nil) {
        whiteSpaces = [NSString string];
    }
    NSLog(@"%@%@", whiteSpaces, self);

    NSString *adjustedWhiteSpaces = [whiteSpaces stringByAppendingFormat:@"    "];

    for (UIView *subview in self.subviews) {
        [subview logViewHierarchy:adjustedWhiteSpaces];
    }
}
@end

1

这个答案中发布的代码遍历所有窗口、所有视图以及它们的子视图。 它被用于将视图层次结构的打印输出转储到NSLog中,但您可以将其用作任何遍历视图层次结构的基础。它使用递归C函数来遍历视图树。


0

我认为所有使用递归的答案(除了调试器选项)都使用了类别。如果您不需要/想要类别,可以只使用实例方法。例如,如果您需要获取视图层次结构中所有标签的数组,则可以执行此操作。

@interface MyViewController ()
@property (nonatomic, retain) NSMutableArray* labelsArray;
@end

@implementation MyViewController

- (void)recursiveFindLabelsInView:(UIView*)inView
{
    for (UIView *view in inView.subviews)
    {
        if([view isKindOfClass:[UILabel class]])
           [self.labelsArray addObject: view];
        else
           [self recursiveFindLabelsInView:view];
    }
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    self.labelsArray = [[NSMutableArray alloc] init];
    [self recursiveFindLabelsInView:self.view];

    for (UILabel *lbl in self.labelsArray)
    {
        //Do something with labels
    }
}

0

这将显示层次结构级别

@implementation UIView (ViewHierarchyLogging)
- (void)logViewHierarchy:(int)level
{
    NSLog(@"%d - %@", level, self);
    for (UIView *subview in self.subviews)
    {
        [subview logViewHierarchy:(level+1)];
    }
}
@end

0

我之前写了一个类别以便调试一些视图。

如果没有记错,发布的代码就是能工作的那个。如果不是,它也会指向正确的方向。使用时请自行承担风险等等。


0

真希望我先找到了这个页面,但如果(出于某种原因)你想以非递归的方式、不在类别中且使用更多行代码来完成此操作


-1
下面的方法创建一个或多个可变数组,然后循环遍历输入视图的子视图。在这样做时,它添加初始子视图,然后查询是否有该子视图的任何子视图。如果是,则再次调用自身。直到所有层次结构的视图都被添加为止。
-(NSArray *)allSubs:(UIView *)view {

    NSMutableArray * ma = [NSMutableArray new];
    for (UIView * sub in view.subviews){
        [ma addObject:sub];
        if (sub.subviews){
            [ma addObjectsFromArray:[self allSubs:sub]];
        }
    }
    return ma;
}

使用以下方式进行调用:

NSArray * subviews = [self allSubs:someView];

1
请使用[编辑]链接来解释这段代码的工作原理,而不仅仅是提供代码,因为解释更有可能帮助未来的读者。另请参见[答案]。来源 - Jed Fox
1
请看我的上方评论。 - Jed Fox

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