SNV7
SNV7

Reputation: 2593

Dynamically name labels in objective c

I'm new to iOS development, just had a quick question. I'm creating an app with 100 UILabel's. Each label is numbered 0 to 99. The problem is that I dont want to do this for all 100 labels.

output1.text = [[NSString alloc] initWithFormat:@"1"];
output2.text = [[NSString alloc] initWithFormat:@"2"];
.....
output100.text = [[NSString alloc] initWithFormat:@"100"];

Instead I'd like to do this a little more dynamically. Below I'm trying to use loops to dynamically create a string. For example by appending "1.text" to the end of "output" I get the string "output1.text".

for (int i=0; i< 100; i++) {
    outputNameString = [NSMutableString stringWithCapacity:0];
    [outputNameString setString:@"output"];
    [outputNameString appendString:[NSString stringWithFormat:@"%i.text",i + 1]];
    outputNameString = [[NSString alloc] initWithFormat:@"%@",i];
}

"output1" to "output100" are properly declared in the interface section and synthesized properly. Is there something I'm missing here, or is this simply not possible? Any help would be appreciated.

Upvotes: 3

Views: 11887

Answers (6)

DoS
DoS

Reputation: 1474

i may be a little late to the show here. i am not quite sure if you are wanting to name the uilabels or set the text property of the uilabels? from your example code it looks like you are trying to set the text, given you have said you synthesized them already. if thats the case, i can name that tune with one line, bob! kvc (key-value coding) i think if your best bet...

for (int i=1; i< 101; i++)
{
    [self setValue:[NSString stringWithFormat:@"%i", i] forKeyPath:[NSString stringWithFormat:@"output%i.text", i]];
} 

the end result would be like doing this...

output1.text = @"1";
// repeat...
output100.text = @"100";

if you wanted to set the tags you could do the same with...

for (int i=1; i< 101; i++)
    {
        [self setValue:i forKeyPath:[NSString stringWithFormat:@"output%i.tag", i]];
    } 

that end result would be like doing this...

output1.tag = 1;
// repeat...
output100.tag = 100;

of course you could put both routines in the same for loop if you wanted. if this is what you are after, i would recommend changing your code to this. it's by far the most efficient and "apple like" way of doing it. you could change things around and tweak it how ever you want to make what ever dynamic changes you want. it's a very cool method. it cut down almost 500 lines of code in one of my projects once i figured this out. it's amazing what you learn when you actually read the docs.

Upvotes: 0

nacho4d
nacho4d

Reputation: 45078

Providing you have an array (NSArray) with all your labels, this is a solution:

for (int i=0; i< 100; i++) {
    UILabel *label = [arrayOfLabels objectAtIndex:i];
    label.text = [NSString stringWithFormat:@"output.%d.text", i+1];
}


Edit : Allocating, storing and accessing 100 objects

I think is better to have all label pointers in an array rather than tagging them, specially because you have a hundred! and each time you call viewWithTag: method it searches the view, it's not indexed.

Using NSArray:

@interface Object : SuperObject {
    NSArray *labels;
}
@end
@implementation
- (void)someMethodThatCreatesLabels {
    labels = [[NSMutableArray alloc] initWithCapacity:100];
    for(NSInteger i = 0; i < 100; i++){
        UILabel *label = [[UILabel alloc] ...];
        label.text = [NSString stringWithFormat:@"output.%d.text", i+1];
        [view addSubview:label]
        [labels addObject:label];
        [label release];
    }
}
- (void)methodThatAccessALabel{
    UILabel *label45 = [labels objectAtIndex:45];
    // Do your thing ...
}
- (void)dealloc{
    [labels release];
    [super dealloc];
}
@end

Using C arrays, which Is a bit shorter (labels[i] instead of [labels objectAtIndex:i])

@interface Object : SuperObject {
    UILabel **labels;
}
@end
@implementation Object
- (void)methodThatCreatesLabels
{
    labels = malloc(100*sizeOf(UILabel *));
    for(NSInteger i = 0; i < 100; i++){
        labels[i] = [[UILabel alloc] ...];
        labels[i].text = [NSString stringWithFormat:@"output.%d.text", i+1];
        [view addSubview:labels[i]]
    }
}
- (void)methodThatAccessALabel{
    UILabel *label45 = labels[45];
    // Do your thing ...
}
- (void)dealloc{
    for(int i = 0; i<100; i++) [labels[i] release];
    free(labels);
    [super dealloc];
}

Upvotes: 2

Shubhank
Shubhank

Reputation: 21805

when you create the label.. set them tags from lets say (100---200 )

so . initialize your label like this..

 for (int i=0; i< 100; i++) {

UILabel *label = [[UILabel alloc] init] ;
// label formatting code here...

label.tag = i+100;
   }

then get your label like this..and set its text

for (int i=0; i< 100; i++) {

UILabel *myLabel = (UILabel *)[self.view viewWithTag:i+100]; // get the label with tag
myLabel.text = [NSString stringWithFormat:@" Label %d",i+1"];
}

this should work great.. What is the problem.?

Upvotes: 10

Swapnil Luktuke
Swapnil Luktuke

Reputation: 10475

When you say, 'Each label is numbered 0 to 99', you mean they have those tags right? If yes, start your tags from 1 to 100 not 0 to 99. If no, set tags for each label. (If you dont know what tags are, read about 'tag' property in UIView documentation)

Then, you can easily access these labels in a loop:

for(int i = 1; i <= 100; i++)
{
    [[self.view viewWithTag:i] setText:[NSString stringWithFormat:@"Output%d.text",i]];
}

If you have not already created all the labels in a view, i would suggest creating the labels programmatically, in a loop and set the tags. Since you can easily access them using the tags, you need not declare them as properties either.

Upvotes: 0

Ravin
Ravin

Reputation: 8564

In iOS you can manage views by tagging them. So for your purpose you can create a base view, on this you will add all the labels with proper tags. Later on whenever you need particular label just query view with method viewWithTag.

Here is how you can implement it:

Creating labels:

UIView *baseView = [[UIView alloc] init];
//keep its reference for later use.. you will need to make it instance variable if you want to access labels in other than this method.

for(int i=0;i<100;i++)
{
   UILabel *label = [[UILabel alloc] init];
   label.tag = i+1; //we are offsetting its value by 1 because tag=0 is for the baseview itself.
   label.text = <the text you wish to assign>;
   [baseView addSubview:label];
   [label release]; //if you are not using ARC.
   label = nil;
}

Accessing labels:

UILabel *label = (UILabel *)[baseView viewWithTag:<provide the tag value you wish to access>];

For more information about UIView tagging you can refer documentation.

Upvotes: 0

EmilioPelaez
EmilioPelaez

Reputation: 19884

The way to get variables with "variable" names is arrays.

You can do one of two:

UILabel *output[100];
for(NSInteger i = 0; i < 100; i++){
  output[i] = [[UILabel alloc] ...];
}

This will declare an array of 100 labels, from 0 to 99, and you can access them like this:

[output[50] setText:text];

The other way is:

NSMutableArray *outputLabels = [[NSMutableArray alloc] initWithCapacity:100];
for(NSInteger i = 0; i < 100; i++){
  UILabel *label = [[UILabel alloc] ...];
  [outputLabels addObject:label];
}

And access them like this:

[[outputLabels objectAtIndex:50] setText:text];

In general, you should read about C arrays, and then read the documentation about NSArray and NSMutableArray.

Upvotes: 1

Related Questions