Назначение свойства readonly

у меня есть следующий код:

-(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).

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

8 ответов


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


  • можно ли назначить свойство, которое только для чтения?

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

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

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

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

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

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

Я.е

_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;
  }

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


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


можно ли назначить свойство только для чтения?

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

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

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


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

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

    _title = t;
    

можно ли назначить свойство только для чтения?

если вы @synthesize coordinate;, тогда будет назван поддерживающий Ивар coordinate. Если свойство автоматически синтезируется, оно будет называться _coordinate.

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

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


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

нет, не должен. Используйте прямой доступ в частично построенном состоянии, таком как инициализатор или -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

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

Source.h

@property (readonly) BOOL  isRunning;

Source.m

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

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