1

I found some code that looks like:

if (statisticsObject.idag3_orig != 0) {
    statisticsView.idag3.text = [NSString stringWithFormat:@"%i",statisticsObject.idag3_orig];
} else {
    float compare1 = statisticsObject.idag2;
    float compare2 = statisticsObject.idag3;
    float result = compare1 + (compare1 * (compare2 / (float) 100.00));
    int final = (int)roundf(result);
    statisticsView.idag3.text = [NSString stringWithFormat:@"%i",final];
}

if (statisticsObject.igar3_orig != 0) {
    statisticsView.igar3.text = [NSString stringWithFormat:@"%i",statisticsObject.igar3_orig];
} else {
    float compare1 = statisticsObject.igar2;
    float compare2 = statisticsObject.igar3;
    float result = compare1 + (compare1 * (compare2 / (float) 100.00));
    int final = (int)roundf(result);
    statisticsView.igar3.text = [NSString stringWithFormat:@"%i",final];
}

This is repeated many, many times. Obviously it doesn't feel very DRY, and is a bit of a pain to work with. How can I loop this logic with variable property names? I think the approach I've taken isn't allowed by Objective-C. Here's what I tried:

NSArray * properties = [[NSArray alloc] initWithObjects:
                                              @"foo",
                                              @"bar",
                                              @"spam", 
                                              nil];
for (id prop in properties) {
    NSLog(@"%@",obj.prop);
}

-- note --

My original pseudo-code was rather confusing. Sorry about that.

To put it simply, how can I restructure my code above so that I'm not constantly repeating myself? The mathematical operations performed are always the same.

3 Answers 3

1

This is mostly an architecture problem. Why 'foo1', 'foo2' and 'foo3' are not grouped in an object? They are integers, why not using an object with three integer properties x, y and z? Then define a method updateText on such object and call:

NSArray * properties = [[NSArray alloc] initWithObjects:
                                              obj.foo,
                                              obj.bar,
                                              obj.spam, 
                                              nil];
for (MyObject* object in properties) {
     [object updateText];
} 

Of course, what you want is also possible, accessing Obj-C runtime. The simplest solution would be to use NSSelectorFromString, e.g.

SEL sel1 = NSSelectorFromString([NSString stringWithFormat:@"%s%i", @"foo", 1]);

and then use performSelector, also with a NSInvocation to get primitive types.

Sign up to request clarification or add additional context in comments.

8 Comments

I think I'm only confusing myself and others now. I've updated my question with the actual code I'm working with, not pseudo-code.
My answer is still valid, abstract all the idag... and igar... properties into an object and make a method on it. Having properties named idag1, idag2 and idag3 is definitely wrong. There should be only one property called idag with properties to access the floats 1 2 and 3 - with better names that just numbers, of course.
Sorry, I've tried it so many ways, and I just can't get it to work. I'm using ARC, which is preventing implicit type conversion. This feels as though it's much more complicated than it needs to be. Why is it so hard to iterate over some properties? Why can't I just switch out the property name for a variable? Here's what I'm trying to make work now: pastie.org/5401172
It's hard because it's something you shouldn't be doing! Please, read again the first part of my answer. The simplest solution is to redesign your architecture - you are using an object oriented language, so why are you not creating objects? Properties ending at numbers are always terrible.
Because it's outside the scope of the project. I agree with you. It's written poorly. My choices are to try and eliminate some repeated code, or effectively write the program from the ground up. The latter is just not viable. I don't understand why it's so hard to use a variable in place of a property like you can with other languages.
|
0

I don;t understand your second code, this is what it would work if you want to print the strings:

NSArray * properties = [[NSArray alloc] initWithObjects:
                                          @"foo",
                                          @"bar",
                                          @"spam", 
                                          nil];
for (id obj in properties) {
    NSLog(@"%@",obj);
}

1 Comment

Ah, sorry, it was a little confusing. If the object is obj, I would like to iterate over its properties, effectively doing NSLog(@"%@",obj.foo);, then NSLog(@"%@",obj.bar); etc.
0

With some care this code should work:

    NSArray * properties = [[NSArray alloc] initWithObjects:
                        @"foo",
                        @"bar",
                        @"spam",
                        nil];
for (id obj in properties)
{
    SEL selector = NSSelectorFromString(obj);
    if (selector && [statisticsView respondsToSelector:selector])
        NSLog(@"%@",[statisticsView performSelector:selector]);
}

please note that the NSLog may break if your properties don't return an NSObject

1 Comment

Couldn't make it work. I think my original pseudo-code was confusing. Sorry about that. I've updated my question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.