Что произойдет, если мы объявим все свойства слабыми? - PullRequest
0 голосов
/ 16 января 2019

Например, есть класс

@interface Person: NSObject {
    @property (weak) NSString *str;
@end

@implementation
    - (void) init {
      str = @"XYZ";
    }
@end
  • Безопасно ли объявлять все свойства слабыми, чтобы избежать подсчета ссылок накладные расходы?
  • Если не безопасно, то почему это не безопасно?
  • Каким будет счетчик ссылок str?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Безопасно ли объявлять все свойства слабыми, чтобы избежать затрат на подсчет ссылок?

Это проблематично по двум причинам. Во-первых, weak не избегает подсчета ссылок. На самом деле он выполняет больше бухгалтерии, чем strong. См. Много накладных расходов для слабого свойства? для хорошего обсуждения этого.

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

Если не безопасно, то почему это не безопасно?

Это абсолютно безопасно. Это просто не сработает. Ваша программа будет иметь четко определенное поведение и не должна падать из-за пометки всех ваших свойств weak. Большинство ваших свойств будет просто nil. Если бы вы использовали unsafe_unretained вместо weak, тогда вы избежали бы некоторых накладных расходов на подсчет ссылок, и ваша программа, как правило, зависала (поскольку объекты все равно будут уничтожены, указатели просто станут недействительными).

Каким будет счетчик ссылок str?

Это не значимый вопрос, даже если кажется, что он один. В данном конкретном случае ответом является 9 223 372 036 854 775 807, потому что это всегда счетчик сохранения статической строки, поскольку статические строки нельзя уничтожить и игнорировать вызовы сохранения / освобождения. (Это значение NSNotFound в ObjC. Я считаю, что раньше оно возвращало 1 152 921 504 606 846 975, но мои тесты показывают, что оно изменилось.)

Но в общем случае это может быть что угодно в данный момент времени. И то, что происходит в данный момент времени по сравнению с концом цикла событий (когда истощается автозапуск), может сильно отличаться. Не гонитесь за сохранением значений счета. Они всегда будут лгать тебе. Создайте сильные ссылки на вещи, которые вас волнуют. Создавайте слабые ссылки только тогда, когда они нужны вам для специальных целей.

Сохранять счетчики - это внутренняя деталь реализации. До ARC они вводили в заблуждение до бесполезности . Начиная с ARC, они как бы спрашивают «к каким инструкциям по сборке это будет компилироваться». Это важно, но это зависит от всего остального в программе и от того, как она компилируется.

Если у вас есть конкретная проблема с производительностью, связанная с управлением памятью, то есть методы для решения этой проблемы в каждом конкретном случае, и StackOverflow может вам помочь. Но ARC чрезвычайно хорош в оптимизации управления памятью. Пусть это сделает свое дело.

0 голосов
/ 16 января 2019

Вы должны знать, какие свойства должны быть слабыми, а какие сильными. Например, общепринятая практика объявляет, например, все IBOutlets как слабые, потому что они сохраняются представлением, исходящим из раскадровки, поэтому нет необходимости сохранять сильную ссылку в viewcontroller.

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

В вашем случае str будет равен nil после init, потому что нет других ссылок на его содержимое. На самом деле вы должны получить предупреждение компилятора, если вы сделаете это.

Посмотрите на эту ветку с более подробным объяснением: Слабые и сильные атрибуты установщика свойств в Objective-C

...