Ленивая инициализация структур C - PullRequest
0 голосов
/ 13 февраля 2012

Я не уверен, как инициализировать свойство класса, которое является структурой 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 ]

5 голосов
/ 13 февраля 2012

Все члены класса objc будут инициализированы нулем при создании (даже структура).Я не понимаю, как вы распределяете память.Пространство зарезервировано для структуры (вы не храните указатель на нее).Для этого потребуется одинаковое пространство независимо от того, присвоили ли вы ему значение или нет.

0 голосов
/ 13 февраля 2012

Ленивая оценка 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

Но я бы не рекомендовал использовать второй.

0 голосов
/ 13 февраля 2012

Как правило, для указателей у вас должно быть внутриполосное недопустимое состояние, например nil. В вашем случае вы можете проверить !CGPointEqualToPoint(_origin, CGPointZero) или !CGPointEqualToPoint(_origin, CGPointMake(-1,-1)), если знаете, что они никогда не будут действительными. (_origin по умолчанию будет CGPointZero или вам придется установить его на (-1, -1) в init, если (0, 0) допустимо.)

Если все возможные внутриполосные значения действительны, вы застряли с внеполосным флагом, как вы упомянули.

...