2

I am trying to condense my code for a method and was wondering how I would achieve the following:

I have a bunch of variables that differ only in their number such as:

int intVariable1
int intVariable2
UILabel Label1
UILabel Label2
BOOL bool1
BOOL bool2

etc.

So I want to call a method and pass in an int. That int would determine which ints, UILablels, and BOOLs get worked on. So if a 1 was passed in the method would work on these variables like this:

- (void) DyanamicMethod: (int) inputNumber {
     //something that uses the inputNumber to act on the 1 variables

     intVariable1 = someValue;
     [Label1 setText:someText];
     bool1 = YES;
}

Obviously if a 2 were passed in I would want the variables to be of the 2 type. I'm assuming you would do something with creating a string somehow, but I'm not sure how to adjust that to use it to become a variable name. Any insight would be appreciated. Thank you for your time.

MarcZero
  • 339
  • 8
  • 20

5 Answers5

4

Declare the variables as arrays:

int intVariable[2];
UILabel *Label[2];
BOOL bools[2];

Then the method would look like this:

intVariable[inputNumber] = someValue;
[Label[inputNumber] setText:@"someText"];
bools[inputNumber] = YES;

Keep in mind that array indexes are zero-based so in the arrays above, variable "1" is at index 0 and variable "2" is at index 1. Your method could also just take the inputNumber and subtract one from it to get the array index.

  • I actually always keep my numbered variables 0 based so the switch should be easy. This looks good. I will adjust my code and try this. Thanks. – MarcZero Jan 17 '10 at 15:56
  • 1
    The only downside here is that you won't be able to set up your IBOutlets in IB with arrays. – Ben Gottlieb Jan 17 '10 at 16:25
  • Why use 'C' style arrays over NSArray? Using an NSArray you can use fast enumeration to iterate over the values held in it. – James Jan 17 '10 at 16:26
  • Ben, James: Thanks, those are both good points. Based on the requirements, choose the method that works best. –  Jan 17 '10 at 16:34
  • Yes. I have tried this and so far, it is not playing nice. Perhaps I should try using a NSArray instead of a C array. – MarcZero Jan 17 '10 at 17:09
  • Ok, can you give more details of the problem you encountered? –  Jan 17 '10 at 17:22
  • @James: `NSArray` is slower, `NSArray` is not strongly-typed, `NSArray` cannot store `BOOL`-s and `int`-s natively, accessing elements in `NSArray` is painful, `NSArray` uses extra heap space, `NSArray` cannot store `nil` directly, `NSArray`'s fast enumeration takes much more code space and a bit more time then C's normal enumeration, `NSArray` store stuff non-locally compared with C array, you cannot know the size of the `NSArray` until you `-count` which again takes more code space and time, etc, etc. – kennytm Jan 17 '10 at 19:15
  • To be fair, `NSArray` performs boundary checks which could save a lot of vulnerability due to lazy programmers. (and `NSArray` can have its size determined at runtime but it's not in the scope here.) – kennytm Jan 17 '10 at 19:17
  • Kenny surely the first thing any programmer should worry about is readability? Personally I find NSArray to be a much easier to work with and understand, commands like: `[arrayName insertObject:]` are incredibly handy. I'll agree the lack of strong typing can be an issue though... – James Jan 17 '10 at 21:59
  • DyingCactus: I'm new to Objective-C and the errors it produces, but I believe the main issues I came across were dealing with the synthesized getters and setters. I couldn't synthesize an arrayed object. Not being able to link object in IB would be problematic too although I didn't try to do that. I undid my steps to before my array adjustments and am looking to try something else. I'm currently reading the options listed here by everyone. – MarcZero Jan 18 '10 at 00:25
  • MarcZero, looks like you'll have to use a combination of the solutions here. NSArrays are easier to make into properties (although exposing class variables that way may not be an ideal design). As noted by Ben, C arrays and NSArray can't be used as IBOutlets (but the UI can be created and hooked up programmatically without IB). Anyway, C arrays have their use and I hope this helped some. –  Jan 18 '10 at 03:40
  • @James: Firstly, `-insertObject:` doesn't belong to `NSArray`. An `NSArray` is immutable. `NSMutableArray` has much more advantages than dynamic C arrays. Secondly, these commands are clear, yes, but annoying when it is needed frequently (e.g. `[arr objectAtIndex:4]` vs `arr[4]`). But maybe that's a good thing to remind you `-objectAtIndex:` involves the (relatively) expensive table lookups and indirect function calls and locking etc. while `a[x]` is just a simple addition and pointer dereference. – kennytm Jan 18 '10 at 08:55
  • DyingCactus: Since this isn't need to get my code to function, only to condense it and make it more readable, I have decided to revisit this problem later on when I am more comfortable with the SDK and Objective-C. I will have to take some time and learn how to set up the outlets manually without IB. Thank you for your help and continued assistance. – MarcZero Jan 18 '10 at 14:45
4

You can use key-value coding.

- (void) DyanamicMethod: (int) inputNumber {
     //something that uses the inputNumber to act on the 1 variables

     NSString* key = [NSString stingWithFormat:@"Label%i", number];
     UILabel* label = [self valueForKey:key];
     label.text = newString;
}
gcamp
  • 14,622
  • 4
  • 54
  • 85
  • Umm, I didn't know about valueForKey More information here: http://stackoverflow.com/questions/1062183/objective-c-whats-the-difference-between-objectforkey-and-valueforkey – Eld Jan 17 '10 at 16:06
3

If you needed something like that you could keep an NSArray of all of the labels ... Like in the class interface section:

NSArray* labels ;

In init:(or loadView)

labels = [[NSArray alloc] initWithObjects:Label1, Label2,etc] ;

In dealloc:

[labels release] ;

in DyanamicMethod: (int) inputNumber

UILabel* label = [labels objectAtIndex:inputNumber] ;

Repeat for each type ... Or make a new class holding the label, int and the bool, and have the array be of that type.

Another way might be:
Make properties for each of your member variables.
Then in your function:

UILabel label1 = [self performSelector:sel_getUid([[NSString stringWithFormat:@"label%d", inputNumber] UTF8String])] ;

I think using an array of some sort is better for this situation, but its possible to do it this way. See NSObject Documentation for performSelector.

Eld
  • 974
  • 6
  • 9
0

You could do this with properties (well, you don't NEED properties, but they'd make it simpler), though you'd have to switch to objects:

@property (nonatomic, readwrite, retain) NSNumber *variable1, *variable2;
@property (nonatomic, readwrite, retain) NSNumber *bool1, *bool2;
@property (nonatomic, readwrite, retain) UILabel *label1, *label2;

- (void) DyanamicMethod: (int) inputNumber { 
    [[self valueForKey: [NSString stringWithFormat: @"label%d", inputNumber] setText: someText];
    [self setValue: [NSNumber numberWithInt: inputNumber] 
            forKey: [NSString stringWithFormat: @"variable%d", inputNumber]];
    [self setValue: [NSNumber numberWithBool: YES] 
            forKey: [NSString stringWithFormat: @"bool%d", inputNumber]];
}
Ben Gottlieb
  • 85,404
  • 22
  • 176
  • 172
-1

Do you have too many variables for a simple switch statement?

switch(inputNumber) {
  case 1:
    intVariable1 = someValue;
    [Label1 setText:someText];
    bool1 = YES;
    break;
  case 2:
    intVariable2 = someValue;
    [Label2 setText:someText];
    bool2 = YES;
    break;
// etc
}
sbooth
  • 16,646
  • 2
  • 55
  • 81
  • Not too many. I could do it this way. I have been doing it with a series of if statements. I would imagine there would be a way to do this dynamically but I'm don't see anything in my searches. I'm not sure if I am using the correct search terms. I'm just trying to condense my code if possible. – MarcZero Jan 17 '10 at 15:44