7

I need a way to get all UILabels within a UIView without having to go through all the views within the UIView.

I have many other type of views, UIButtons, UIImageViews and it would be too long to go through all of them when I just need the UILabels.

I'm trying to avoid something like this:

for (UIView *view in myView.subviews) 
{
    if([view isKindOfClass:[UILabel class]])
    {
        UILabel *lbl = (UILabel*)view;
    }
}

Is it possible or am I dreaming?

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
subharb
  • 3,374
  • 8
  • 41
  • 72

4 Answers4

6

Create an NSArray ivar which you can add all the UILabel's to.

If you do it in code then as you create the UILabel just do

NSMutableArray *labels = [[NSMutableArray alloc] init];

// Repeat this for al labels
UILabel *label = [[UILabel alloc] in...
[labels addObject:label];

// Then
self.labels = [labels copy];

If you use IB the declare your property like this

@property (nonatomic, strong) IBOutletCollection(UILabel) NSArray *labels;

and connect all the labels up to this.

Paul.s
  • 38,494
  • 5
  • 70
  • 88
4

Man, you need make use recursion. (If you don't want use tags)

Try This.

-(UIView *)checkChild:(UIView *)view{

    NSArray *arrayView = view.subviews;
    UIView *returnView = nil;

    for (UIView *auxView in arrayView) {
        if ([auxView isKindOfClass:[UILabel class]]) {
            return auxView;
        }else{
            returnView = [self checkChild:auxView];
        }
    }
    return returnView;
}
Alex Cio
  • 6,014
  • 5
  • 44
  • 74
  • Nice snippet, you should just return an array of elements found on your path instead of returning a single element. You will also just get the last element from the subviews of the class you are looking for because you always overwrite the last element with a new value. – Alex Cio May 16 '15 at 21:55
2

I liked the approach of @SiddharthaMoraes, but changed it to collect all the elements found on its path. I was looking for the UILabels inside my UIViewController and couldn't find them because they where nested inside another UIView, so this recursion should solve the problem:

-(NSMutableArray *)checkChild:(UIView *)view{

    NSArray *arrayView = view.subviews;
    NSMutableArray *arrayToReturn = [NSMutableArray new];

    for (UIView *auxView in arrayView) {
        if ([auxView isKindOfClass:[MyLabel class]]) {
            [arrayToReturn addObject:auxView];
        }else if( auxView.subviews ){
            [arrayToReturn addObjectsFromArray:[self checkChild:auxView]];
        }
    }
    return arrayToReturn;
}
Alex Cio
  • 6,014
  • 5
  • 44
  • 74
1

You can set the tag property for the label.. something like this...

label.tag = 100;

UILabel *lbl = [yourView viewWithTag:100];
Aravindhan
  • 15,608
  • 10
  • 56
  • 71
  • Yuk don't use `viewWithTag:` there are much better ways – Paul.s Apr 12 '12 at 16:57
  • @Paul.s : thank you for the comment.. May I know what is the disadvantage of using viewWithTag? – Aravindhan Apr 12 '12 at 17:02
  • 1
    FYI I was going to down vote, but I decided it would be a bit harsh as I see this suggestion a lot. It's just a bit naff/lazy - if you need a reference to a view and you know you need it, then why not make an ivar out of it? I don't like the idea of trawling through a potentially large view hierarchy asking each tag for an arbitrary value that can accidentally be changed. Also in the this case the OP wanted multiple views returned, which this API would not do. – Paul.s Apr 12 '12 at 17:08
  • Its just a single `UILabel`, the question was, how to change many views once. Offtopic – Alex Cio May 16 '15 at 19:25