2013-07-18 2 views
9

Я следующий код:Назначение только для чтения свойства

-(id) initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t 
{ 
    self = [super init]; 

    if (self) 
    { 
     coordinate = c; 
     self.title = t; 
    } 

    return self; 
} 

где coordinate является:

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 

У меня было два вопроса:

  • это ОК, чтобы присвоить свойству, которое только для чтения?
  • не должно coordinate есть self не нужно? (например, self.coordinate = c).

пс. Я не получаю никаких ошибок с помощью этого кода - и это пример из книги.

+1

Если у вас есть свойство readonly, вы не можете назначить ему какую-либо вещь, компилятор даст ошибку в этом случае. – Suryakant

+0

Вы должны получить проблему с компиляцией при назначении на чтение, установлено ли значение readwrite в другом месте? Вы синтезируете? – Wain

+0

@ Wain: да, я синтезировал. Я не получаю проблемы с компилятором –

ответ

14

Вы должны написать: self.coordinate = c который равен [self setCoordinate:c] - метод вызова сеттера. Но вы не можете этого сделать, потому что получите ошибку Assignment to readonly property. Свойства только для чтения не имеют методов setter. В вашем случае вы просто устанавливаете ivar, который поддерживает свойство напрямую, и это хорошо документированное поведение. Имя ivar будет именем свойства с префиксом подчёркивания, но в вашем случае у вас есть явный @synthesize, как вы сказали, поэтому у ivar будет одно имя, и поэтому у вас нет проблем с компилятором. Свойство доступно для публичного доступа только для чтения, но оно может быть записано классом - это включает либо объявление метода setter в расширении класса, либо повторное использование свойства в расширении. Для этого вы можете сослаться на этот пост: Objective-C property that is readonly publicly, but has a private setter

+0

Он уже делает это, установив ivar ... –

+0

Он использует синтезированный сеттер. –

0
  1. Нет, это не нормально. Правильный способ назначить readonly как это:

    - (CLLocationCoordinate2D)coordinate { 
    
        //create the struct and return it. 
    
        return value; 
    
    } 
    
  2. Нет, это наоборот. Вы должны установить title так:

    _title = t; 
    
+0

Но название не только для чтения. –

0

Линия coordinate = c; не присваивая собственность, это присвоение переменной экземпляра, который имеет такое же имя. Невозможно назначить свойство readonly, это значит, что означает только «чтение». Если вы измените его на self.coordinate = c, вы получите сообщение об ошибке, если это свойство не будет объявлено как readwrite в расширении класса.

3
  • ОК, чтобы присвоить собственность, которая является только для чтения?

    Да, это нормально, если вы не хотите, чтобы свойство было мутировано вне его содержащего экземпляра.

    например: свойство count массива, здесь count является свойством, которое зависит от количества объектов, сохраненных массивом. Поэтому его нельзя изменять вне объекта Array.

  • не должен координировать себя перед этим? (например, self.coordinate = c).

    Если вы читаете только, вы не можете изменить свою собственность с помощью метода setter.

    сам.координата преобразуется в [self setCoordinate:], которая недопустима, поскольку чтение только предотвращает изменение методов настройки при изменении свойства.

Таким образом, вы должны непосредственно установить ivar, и это может быть сделано только внутри объекта, для которого определяется только для чтения свойства.

т.е.

_coordinate = value; //or coordinate = value if you have synthesized it. 

Если вам интересно,

self.propertyName && self.property = indirectly calls getter and setter method. 

И в реализации, сеттеры и геттер помощь в _ivars быть публичным союзник доступным является собственностью является общедоступным.

- (void)setProperty(value) //self.property = value 
{ 
    _property = value; 
} 

- (id)property //self.property 
    { 
    return _property; 
    } 
+0

Я вижу, поэтому в Obj. C это нормально ссылаться непосредственно на переменные экземпляра, например, 'myVariable = 13;' (без self) –

+0

вы не можете, если у вас нет @synthesized. В противном случае вам нужно обратиться к нему как _varName –

0

это ОК, чтобы присвоить свойству, который доступен только для чтения?

Если вы используете синтезированные аксессоры, как вы делаете, это прекрасно.

не должен координировать себя перед этим? (например, self.coordinate = c).

self.coordinate - это ярлык для несинхронизированного доступа. Этот сеттер виден вне класса, поэтому, поскольку свойство должно быть только для чтения для пользователей класса, вы получаете ошибку компилятора, если пытаетесь получить доступ к свойствам readonly с помощью точечной нотации. Ваш код верен.

0

ОК, чтобы присвоить свойство, которое только для чтения?

Если вы @synthesize coordinate;, то поддержка ivar будет называться coordinate. Если свойство автосинхронизировано, оно будет называться _coordinate.

Если вы намерены назначить основную переменную экземпляра в инициализаторе, это нормально (например, coordinate = c или _coordinate = c).

Если вы хотите установить его с помощью сеттер (например [self setCoordinate:c] или self.coordinate = c; вам необходимо реализовать связующий самостоятельно или синтезировать его определение (например, путем объявления READWRITE собственности в своем классе продолжение).


не должны скоординировать у себя перед ним? (например, self.coordinate = с).

нет, it should not. Использование прямого доступа в частично построенном состоянии, например, элемента инициализатор или -dealloc.

Учитывая свойства:

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 
@property (nonatomic, copy, readwrite) NSString * title; 

Ваш инициализатор должен принять форму:

- (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t 
{ 
self = [super init]; 

if (self) 
{ 
    _coordinate = c; 
    _title = t.copy; // note: copy/ownership semantics match property declaration 
} 

return self; 
} 

@end 
0

Я видел хитрые люди делают это ....

Source.h

@property (readonly) BOOL isRunning; 

Source.m

- (void) blahBlahBlah { ... 
    self->_isRunning = YES; ... 

Существует очень мало документация, что я могу найти информацию об этих типах аксессорах ... Я уверен, что это просто стандартный C конструкт ... тот, который я не очень хорошо знаком .. Но это способ пойти, если ваше мастерство предмета ... лучше, чем мое ...

1

вы не можете присвоить значение переменной с свойством readonly, но из iOS6, @synthesize можно добавить автоматически, поэтому вы можете использовать ivar для его замены. Например, _test = @ "test" для замены self.test = @ "test", если свойство теста выполняется только для чтения.

Смежные вопросы