Я объявил свойство readonly в своем интерфейсе как таковое:
@property (readonly, nonatomic, copy) NSString* eventDomain;
Возможно, я неправильно понимаю свойства, но я подумал, что когда вы объявляете его как readonly
, вы можете использовать сгенерированный сеттер внутри .m
файла implementation ( ), но внешние объекты не могут изменить значение. Этот вопрос SO говорит, что это должно произойти. Это то поведение, которое мне нужно. Однако при попытке использовать стандартный установщик или синтаксис точки для установки eventDomain
внутри моего метода инициализации я получаю unrecognized selector sent to instance.
ошибку. Конечно, я @synthesize
в собственности. Пытаюсь использовать это так:
// inside one of my init methods
[self setEventDomain:@"someString"]; // unrecognized selector sent to instance error
Так я неправильно понимаю readonly
декларацию собственности? Или что-то еще происходит?
.h
? В противном случае я не понимаю, как это выставит публичный сеттер. СпасибоЭйко и другие дали правильные ответы.
Вот более простой способ: получить прямой доступ к частной переменной-члену.
пример
В заголовочном файле .h:
@property (strong, nonatomic, readonly) NSString* foo;
В файле реализации .m:
// inside one of my init methods self->_foo = @"someString"; // Notice the underscore prefix of var name.
Вот и все, что вам нужно. Ни суеты, ни суеты.
Детали
Начиная с Xcode 4.4 и LLVM Compiler 4.0 ( новые функции в Xcode 4.4 ), вам не нужно возиться с рутинной работой, описанной в других ответах:
synthesize
ключевое словоПосле объявления свойства
foo
, можно предположить , Xcode добавила закрытую переменную с именем с префиксом подчеркивания:_foo
.Если свойство было объявлено
readwrite
, Xcode генерирует названный метод получения и названныйfoo
установщикsetFoo
. Эти методы неявно вызываются, когда вы используете точечную нотацию (мой Object.myMethod). Если свойство было объявленоreadonly
, сеттер не создается. Это означает, что поддерживающая переменная, названная с подчеркиванием, не предназначена только для чтения. Этоreadonly
просто означает, что метод установки не был синтезирован, и поэтому использование точечной записи для установки значения завершается ошибкой компилятора. Точечная нотация не работает, потому что компилятор не дает вам вызвать метод (установщик), который не существует.Самый простой способ обойти это - получить прямой доступ к переменной-члену, названной с подчеркиванием. Вы можете сделать это даже без объявления этой переменной с именем подчеркивания! Xcode вставляет это объявление как часть процесса сборки / компиляции, поэтому ваш скомпилированный код действительно будет иметь объявление переменной. Но вы никогда не увидите этого объявления в исходном файле исходного кода. Не волшебство, просто синтаксический сахар .
Использование
self->
- это способ доступа к переменной-члену объекта / экземпляра. Вы можете опустить это и просто использовать имя переменной. Но я предпочитаю использовать стрелку self +, потому что она делает мой код самодокументированным. Когда вы видите,self->_foo
вы без двусмысленности знаете, что_foo
это переменная-член в этом экземпляре.Между прочим, обсуждение преимуществ и недостатков средств доступа к свойствам по сравнению с прямым доступом к ivar - это именно та продуманная трактовка, которую вы прочтете в книге доктора Мэтта Нойберга « Программирование iOS» . Мне было очень полезно читать и перечитывать.
источник
readonly
образом, чтобы никакой другой класс не мог его установить.Другой способ, который я нашел для работы со свойствами только для чтения, - это использовать @synthesize для указания хранилища резервных копий. Например
@interface MyClass @property (readonly) int whatever; @end
Тогда в реализации
@implementation MyClass @synthesize whatever = m_whatever; @end
Затем ваши методы могут быть установлены
m_whatever
, поскольку это переменная-член.Еще одна интересная вещь, которую я понял за последние несколько дней, это то, что вы можете создавать свойства, доступные только для чтения, которые доступны для записи такими подклассами:
(в заголовочном файле)
@interface MyClass { @protected int m_propertyBackingStore; } @property (readonly) int myProperty; @end
Тогда в реализации
@synthesize myProperty = m_propertyBackingStore;
Он будет использовать объявление в файле заголовка, поэтому подклассы могут обновлять значение свойства, сохраняя его доступность только для чтения.
К сожалению, с точки зрения сокрытия и инкапсуляции данных.
источник
См. Раздел Настройка существующих классов в документации iOS.
Свойства только для чтения имеют только метод получения. Вы по-прежнему можете установить поддерживающий ivar непосредственно в классе свойства или с помощью кодирования значения ключа.
источник
Вы неправильно понимаете другой вопрос. В этом вопросе есть расширение класса, объявленное таким образом:
@interface MYShapeEditorDocument () @property (readwrite, copy) NSArray *shapesInOrderBackToFront; @end
Это то, что генерирует сеттер, видимый только в реализации класса. Итак, как говорит Эйко, вам нужно объявить расширение класса и переопределить объявление свойства, чтобы компилятор генерировал установщик только внутри класса.
источник
Самое короткое решение:
MyClass.h
@interface MyClass { int myProperty; } @property (readonly) int myProperty; @end
MyClass.h
@implementation MyClass @synthesize myProperty; @end
источник
Если свойство определено как readonly, это означает, что фактически не будет сеттера, который можно использовать либо внутри класса, либо извне из других классов. (то есть: у вас будет только "получатель", если это имеет смысл.)
Судя по звукам, вам нужно обычное свойство чтения / записи, помеченное как частное, чего вы можете добиться, установив переменную класса как частную в вашем файле интерфейса как таковую:
@private NSString* eventDomain; }
источник