views:

311

answers:

5

Hello. 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.

A: 

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
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
+3  A: 
Eld
+4  A: 

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.

DyingCactus
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
The only downside here is that you won't be able to set up your IBOutlets in IB with arrays.
Ben Gottlieb
Why use 'C' style arrays over NSArray? Using an NSArray you can use fast enumeration to iterate over the values held in it.
James Raybould
Ben, James: Thanks, those are both good points. Based on the requirements, choose the method that works best.
DyingCactus
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
Ok, can you give more details of the problem you encountered?
DyingCactus
@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
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
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 Raybould
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
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.
DyingCactus
@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
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
A: 

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
You don't need the `@property`s to participate in KVC.
KennyTM
@KennyTM: Either properties or self-coded accessors, but that's irrelevant to Ben's answer.
Georg
Yeah, I mentioned you don't NEED 'em, but it'll make things a little easier.
Ben Gottlieb
@Georg: Actually an ivar named `variable1` or `_variable1` is enough to use KVC for the key `variable1`. No need to define any accessors.
KennyTM
@KennyTM: You're right, I'm sorry. I should have known that.
Georg
+2  A: 

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
Umm, I didn't know about valueForKeyMore information here: http://stackoverflow.com/questions/1062183/objective-c-whats-the-difference-between-objectforkey-and-valueforkey
Eld