C结构的延迟初始化

时间:2012-02-12 22:47:14

标签: objective-c ios struct lazy-initialization

我不确定如何初始化一个C结构或iOS5之前基类型的类属性。如果我正在处理一个类,这就是我要做的事情,但是我不知道我可以检查这是否是第一次访问该结构,因为它们在创建时未定义:

@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

我意识到延迟初始化的主要好处是内存分配,但是如果我对所有类的属性执行此操作,那么使用相同的样式来设置所有属性的起始值似乎是最明显的。

我可以使用其他一些实例变量或属性来跟踪是否已访问self.origin,但这似乎......不顺利。在设置它之前,我可以注意永远不要访问self.origin,这似乎有点因为结构在创建时未定义。

有“正确”的方式吗?

3 个答案:

答案 0 :(得分:5)

objc类的所有成员将在创建时初始化为零(甚至是结构)。我不指你内存分配。该空间是为结构保留的(您没有存储指向它的指针)。无论您是否为其指定了值,它都需要相同的空间。

答案 1 :(得分:0)

通常,您必须有一个带内无效状态,如nil指针。在您的情况下,如果您知道那些永远无效,您可以测试!CGPointEqualToPoint(_origin, CGPointZero)!CGPointEqualToPoint(_origin, CGPointMake(-1,-1))。 (_origin将默认为CGPointZero,或者如果(0,0)有效,则必须在init中将其设置为(-1,-1)。

如果所有可能的带内值都有效,那么就像你提到的那样,你会遇到一个带外标志。

答案 2 :(得分:0)

CGPoint的懒惰评估可以(至少)以两种不同的方式完成:

干净的方式是存储BOOL,用于保存您的CGPoint是否已初始化的信息。

@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

如果您不想浪费 BOOL内存,您可以采取肮脏的方法 并使用初始值来测试您的_origin

@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

但我建议不要使用第二个。