Подтвердить что ты не робот

Каков правильный способ объявить свойство readonly для ios, используя ARC

Я новичок в разработке iOS в целом и никогда не рассматривал ручной подсчет ссылок (сохранение, выпуск, автореле). Таким образом, я не очень хорошо понимаю, что делает магический ARC.

Я думал, что понял, до тех пор, пока меня не спросят, какой тип собственности (weak, strong, assign и т.д.) должен быть присвоен свойству readonly, указывающему на объект, например:

@property (readonly,nonatomic) NSString* name;

Я читаю здесь Вопросы о readonly @property в ARC, что отказ от strong/weak на самом деле не будет компилироваться, если вы не укажете опорную переменную, если вы @synthesize имущество; Я просто так описал поддержку ивара таким образом:

@synthesize name = _name;

Теперь я понимаю, что по умолчанию "определитель жизненного цикла" переменной силен, отсюда: http://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4

Итак, чтобы сократить длинную историю, я косвенно определяю свое свойство как (readonly,nonatomic,strong), поскольку _name ivar неявно объявляется как __strong.

У меня есть несколько вопросов:

  • Используется ли strong правильный определитель времени жизни? Я предполагаю, что это так, иначе объект, поддерживающий мой NSString*, не будет принадлежать нигде и, таким образом, будет автоматически освобожден (исходя из земли Java, это имеет смысл, поскольку по умолчанию все ссылки сильны).

  • Существуют ли какие-либо другие модификаторы, которые имеют смысл в этой ситуации, например copy или assign?

  • Объявляет ли свойство как (readonly,nonatomic,strong) и (readonly,nonatomic) какое-либо значение для кода, который потребляет свойство? например. объявляет его без ключевого слова strong, потому что указатель объекта должен быть сохранен как __unsafe_unretained, где свойство strong будет храниться в указателе __strong?

Спасибо!

ИЗМЕНИТЬ

Итак, как я понимаю, для свойств readonly применяется следующее:

  • Для типов non-NSObject * (int, float, void * и т.д.) используйте (readonly, assign).
  • Для указателей объектов используйте (readonly, strong) или (readonly, copy) - эти функции одинаковы для свойств readonly, но вам может понадобиться семантика копии, если вы расширяете/подкласс и переопределяете свойство как readwrite.
  • Для указателей объектов (readonly, weak) имеет смысл только в том случае, если вы собираетесь хранить уже слабый указатель в этом свойстве (этот указатель должен быть сильным в другом месте или объект будет освобожден).
4b9b3361

Ответ 1

  • strong корректно использовать, если вы хотите сохранить сильную (владеющую) ссылку на то, что вы указываете. Обычно вам нужно сильное, но для предотвращения циклических ссылок (особенно в отношениях между родителями и детьми, где, если родитель указывает на ребенка, а ребенок указывает на родителя, они никогда не будут выпущены), вам иногда необходимо использовать слабые ссылки, Кроме того, если вы хотите сохранить указатель на объект, который у вас нет, но хотите, чтобы он был действительным только до тех пор, пока он существует, вы хотите использовать слабый указатель, потому что когда он освобождается владельцем, указатель автоматически установится на nil и не укажет на память, что это не должно быть.

  • assign используется со скалярными значениями и является установщиком по умолчанию. copy имеет смысл, если вы хотите автоматически сделать копию объекта и установить указатель на копию вместо указания на исходный объект. Это имеет смысл сделать это, если у вас есть определенная потребность (обычно, потому что вы не хотите, чтобы объект мутировал вас).

  • Ссылка, которую вы указали, которая показывает, что значение __strong является значением по умолчанию (и поэтому вам не нужно указывать его) относится к переменным и не. объявленные свойства. Значение объявленных свойств по умолчанию равно assign, поэтому это, безусловно, будет иметь значение. Если бы вы хотели assign, тем не менее, не имеет значения, укажите ли вы это или нет (кроме просто быть понятным, что это то, что вы хотели). EDIT. Однако, как отметил Жак, это меняется с LLVM 3.1, а по умолчанию изменяется от assign до strong. В этом случае совершенно не имеет значения, укажите ли вы strong или не можете его оставить, если хотите. Лично я считаю, что хорошо изложить это (особенно потому, что существует конфликт между разными версиями), так что каждый, кто смотрит на код, находится на одной странице. Другие могут не согласиться с этим.:)

Я бы предложил прочитать Объявленные свойства раздела Objective-C Язык программирования здесь: <document removed by Apple with no direct replacement>.

Ответ 2

Еще одна точка: свойства могут быть переопределены с readonly до readwrite. Например, подкласс может создавать свойство чтения только для чтения и записи суперкласса, подобно тому, как много классов Cocoa имеют подклассы, которые добавляют изменчивость. Аналогично, свойство может быть общедоступным для чтения, но класс может повторно использовать его для чтения и записи для внутреннего использования в расширении класса. Таким образом, когда класс устанавливает свое собственное свойство, он может использовать синтезированный сеттер, который правильно управляет памятью и генерирует соответствующие уведомления об изменении значения ключа.

В настоящее время все остальные атрибуты свойства должны быть согласованными. Разумеется, компилятор может ослабить это требование. (Некоторые считают, что это ошибка.) Во всяком случае, одна из причин объявить свойство readonly с атрибутом собственности, например strong, copy, или слабым - так, чтобы он соответствовал ремаркетированию readwrite в другом месте.

Что касается вашего вопроса 3, спрашиваете, влияет ли квалификатор собственности на код, вызывающий геттер? Нет, это не так.

Ответ 3

Эти две строки кода работают для меня:

.h файл:

@property (nonatomic, readonly, copy) NSString *username;

.m file:

@property (nonatomic, readwrite, copy) NSString *username;