Property vs Variable


#1

My second question regarding this chapter revolves around the use of properties versus a variable. In this chapter we created two properties, the begin and end points, and two variables (not properties) to hold these values. Why not use properties for the dictionary and array?

Thanks,
Jeff


#2

Basically, you use

properties: if you need to access them in a method of another class
variables: if you only need to access it within the class, where you define it


#3

Thanks, Crumble.

But why? Is there a penalty for using properties? Or is this just a programming choice like the use of camel case for names? Is it just cleaner code and less to write? Is there a reason why you can’t or shouldn’t use a property instead of a variable even if it is only accessed with its own implementation?

Jeff


#4

Since they rely on getters/setters, properties incur some run-time overhead, and they transparently send out KVO notifications.


#5

Thanks, ibex. I imagine that if there aren’t a lot of properties then the difference between @property and a variable would be minimal? Also, doesn’t @property create an instance variable internally? So I suppose there is some added overhead there as well?


#6

By overhead I meant the cost incurred by invoking getter/setter methods associated with properties. This cost can be high.

To see this, run the following example:

//  main.m

#import <Foundation/Foundation.h>

// --------------------------------------------------
//
@interface MyTiming: NSObject
+ (void)start;
+ (double)elapsedTimeInMicroSeconds;
@end

// --------------------------------------------------
//
typedef float RealNumber;

@interface ComplexNumber: NSObject

@property RealNumber realPart;
@property RealNumber imaginaryPart;

- (void)setRealPart:(RealNumber)rp imaginaryPart:(RealNumber)ip directly:(BOOL)directly;

@end

int main (int argc, const char * argv[])
{
    const int N = 1024 * 1024;
    const RealNumber r1 = arc4random_uniform (1024);
    const RealNumber r2 = arc4random_uniform (1024);

    @autoreleasepool {
        ComplexNumber *complexNumber = [[ComplexNumber alloc] init];
                
        int ic = 0;
        [MyTiming start];
        while (ic++ < N) {
            [complexNumber setRealPart:r1 imaginaryPart:r2 directly:NO];
        }
        assert (ic == (N+1));  // detecting optimizatioin tricks
        
        double elapsedTime = [MyTiming elapsedTimeInMicroSeconds];
        NSLog (@"Indirect sets took %f microseconds", elapsedTime);
        
        ic = 0;
        [MyTiming start];
        while (ic++ < N) {
            [complexNumber setRealPart:r1 imaginaryPart:r2 directly:YES];
        }
        assert (ic == (N+1));   // detecting optimizatioin tricks
        
        elapsedTime = [MyTiming elapsedTimeInMicroSeconds];
        NSLog (@"  Direct sets took %f microseconds", elapsedTime);
    }
    return 0;
}

// --------------------------------------------------
//
@implementation ComplexNumber

@synthesize realPart;
@synthesize imaginaryPart;

- (void)setRealPart:(RealNumber)rp imaginaryPart:(RealNumber)ip directly:(BOOL)directly
{
    if (directly) {
        // assign directly
        self->realPart = rp;
        self->imaginaryPart = ip;
    } else {
        // assign through properties
        self.realPart = rp;
        self.imaginaryPart = ip;
    }
}
@end

// --------------------------------------------------
//
@implementation MyTiming

#include <sys/resource.h>

static struct rusage t1;

+ (void)start
{
    getrusage (RUSAGE_SELF, &t1);    
}

+ (double)elapsedTimeInMicroSeconds;
{
    struct rusage t2;
    getrusage (RUSAGE_SELF, &t2);
    double v = ((double) (1000000)) * (double) (t2.ru_utime.tv_sec - t1.ru_utime.tv_sec)
    + (double) (t2.ru_utime.tv_usec - t1.ru_utime.tv_usec);
    return v;
}

@end

For applications that demand high performance, we have to be aware of this cost.


#7

Thanks, ibex. I like the example. I see that the @property method rakes approximately 2.7x the amount of time to execute - 27 ms vs 10 ms. Still, it is a small amount of time. If the program were large and required many calls I can see the benefit of using a simple variable. Thanks again for the code.

Another question I posted related to the separation of the model and view. In this chapter we have the view manipulating the model directly. Is this proper or am I looking at it right? Perhaps it has to work in this manner. I just thought the view controller had to, or was supposed to, play more of a central role in things. Can you shed some light on this topic?

Jeff