0

I'm not sure how to initialize a class property that's a C struct, or pre-iOS5 base type. This is what I'd do if I was dealing with a class, but I don't know what I can check to see if this is the first time the struct has been accessed, since they're undefined at creation:

@interface GraphView : UIView
@property (nonatomic) CGPoint origin;
@end


@implementation GraphView
@synthesize origin = _origin;

- (CGPoint)origin
{
    if (WHAT?) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
    }
    return _origin;
}

@end

I realize the primary benefit of lazy initialization is for memory allocation, but if I'm doing this for all the properties that are classes, it seems clearest to use the same style for setting starting values on all my properties.

I can use some other instance variable or property to track whether the self.origin has been accessed, but that seems... not smooth. I could take care to never access self.origin before I've set it, which seems mildly entailed by the fact that structs are undefined at creation.

Is there a "right" way?

bsdfm
  • 61
  • 5

3 Answers3

5

All members of a objc class will be initialized to zero on creation (even a struct). I do not get you point about memory allocation. The space is reserved for the struct (you are not storing a pointer to it). It will require the same space whether you have assigned it a value or not.

rasmus
  • 3,136
  • 17
  • 22
  • Right. Thank you. I thought that since structs on the stack are undefined until they're set, they'd be undefined here. But duh. – bsdfm Feb 12 '12 at 23:32
  • @rasmus, could you explain this? http://stackoverflow.com/questions/13372551/c-struct-not-initialized-to-zero-in-objective-c – Philip007 Nov 14 '12 at 03:29
0

Generally you have to have an in-band invalid state like nil for pointers. In your case, you could test !CGPointEqualToPoint(_origin, CGPointZero) or !CGPointEqualToPoint(_origin, CGPointMake(-1,-1)) if you know those can never be valid. (_origin will default to CGPointZero or you'll have to set it to (-1, -1) in an init if (0, 0) is valid.)

If all possible in-band values are valid, you're stuck with an out-of-band flag as you mentioned.

smparkes
  • 13,807
  • 4
  • 36
  • 61
0

The lazy evaluation of the CGPoint could be done in (at least) two different ways:

The clean way would be storing a BOOL, that keeps the information whether your CGPoint has been initialized.

@interface GraphView : UIView {
  BOOL _originInitialized;
}
@property (nonatomic) CGPoint origin;
@end

@implementation GraphView
@synthesize origin = _origin;

// extend the init methods
-(id) init {
  ...
  _originInitialized = NO;
  ...
}

- (CGPoint) origin {
    if (_originInitialized) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
         _originInitialized = YES;
    }
    return _origin;
}
@end

In case you do not want to waste a BOOL of memory you could do a dirty approach and use an initial value, to test your _origin against:

@interface GraphView : UIView
@property (nonatomic) CGPoint origin;
@end

@implementation GraphView
@synthesize origin = _origin;

// extend the init methods
-(id) init {
  ...
  _origin = CGPointMake(-23.0, -42.0);
  ...
}

- (CGPoint) origin {
    if (_origin.x == -23.0 && _origin.y == -42.0) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
    }
    return _origin;
}
@end

But I'd recommend not to use the second one.

Tharabas
  • 3,402
  • 1
  • 30
  • 29
  • You're wrong, objective-c objects' memory is zeroed before creation. You can rely on those struct members to be zero. https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/alloc – joerick Feb 12 '12 at 23:15
  • Thanks, did not know that. Must have mixed that up with generic C struct allocation. Modified my answer. – Tharabas Feb 12 '12 at 23:21