Имеет ли readonly свойство для IBOutlet Work и будет ли оно предпочтительным? - PullRequest
6 голосов
/ 02 ноября 2011

В коде, который я наследую, я видел следующее:

@property (readonly) IBOutlet UIImageView * bgImage;

Когда я ожидал, что модель сохранения памяти будет выглядеть следующим образом:

@property (readonly, retain) IBOutlet UIImageView * bgImage;

Я запуталсяпочему первое определение свойства работает без проблем.

Кроме того, в dealloc есть release, как вы могли бы ожидать, например:

-(void)dealloc
{
   [_bgImage release];
   [super dealloc];
}

Буду признателен, если кто-нибудь сможет подойтис объяснением этого.Я разговаривал с первоначальным разработчиком, и он пытался написать более лаконичный код, поэтому он пропустил retain в модели памяти (казалось ненужным).

Интересно, рассматривается ли IBOutlet в основном?как оператор ivar IBOutlet, потому что он доступен только для чтения (не использовать установщик, поэтому модель памяти назначения по умолчанию не имеет значения).

Если IBOutlet никогда не изменится, будет использоваться свойство readonly без модели памятина самом деле быть предпочтительным способом определения свойств?

Ответы [ 2 ]

7 голосов
/ 02 ноября 2011

Загрузчик пера на iOS создает объекты в пиру, а затем автоматически выпускает их. Когда он устанавливает соединения с розетками, он использует setValue:forKey:, что вызовет метод установки для этого ключа. Если сеттер не определен, например, когда IBOutlet является свойством readonly, объект сохраняется в любом случае до назначения. (Это парафраз Управление объектами пера в iOS в Руководстве по программированию ресурсов.)

Таким образом, в действительности, независимо от того, объявлено ли выходное отверстие как retain или assign, объект на другом конце является , принадлежащим объекту с выходным отверстием. Либо он сохраняется методом установщика, либо он сохраняется setValue:forKey:, когда установщик не найден. Поскольку во втором случае нет другого возможного владельца, вы можете считать, что объект с торговой точкой является владельцем. Поэтому объект в кончике должен быть освобожден в dealloc.

Я согласен с вами, что это условие памяти следует сделать явным, изменив атрибуты свойства, включив в него retain. * Независимо от того, является ли оно readonly, кажется, не имеет значения (однако, см. Ниже). Концептуально, да, объект доступен только для чтения, поэтому то, стоит ли пометить его явно как таковое, зависит от того, считаете ли вы его соответствующим образом задокументированным из-за того, что это IBOutlet.

UPDATE: Комментарий Paul.s ниже побудил меня сделать быстрый тест. Я создал подкласс UIView, который регистрирует его вызовы alloc, retain, release и autorelease, вставил его экземпляр в перо и дал делегату приложения IBOutlet через свойство.

Собирая вручную подсчет ссылок, экземпляр получил счетчик 0, когда свойство было (readwrite, assign). Это было чистое +1, когда свойство было объявлено рекомендуемым способом, (readwrite, retain), и также , когда оно было (readonly, assign). Все это в значительной степени, как и ожидалось - когда оно равно (readwrite, assign), установщик назначения используется для установления соединения, и сохранение не производится. Когда он равен readonly, механизм соединения возвращается к выполнению собственного сохранения.

Самое интересное, что когда я пытался завершить работу приложения, изменив цвет фона этого представления с помощью свойства, объявленного (readwrite, assign) (т. Е. Когда оно предположительно было освобождено), я увидел последний вызов retain .

Я думаю, что это сводится к следующему: следуйте рекомендации Apple - они знают, что происходит за кулисами, и (за исключением ошибок) не собираются направлять вас неправильно.

(Еще одна вещь, которую нужно уловить, это то, что, как всегда, беспокоиться об абсолютных счетчиках ссылок не будет ужасно полезно - счетчик пошел до 6 в одной точке за два десятка звонков retain и release - вам просто нужно беспокоиться об удержаниях и выпусках, которые вы вызываете напрямую.)


* Конечно, это меняется под ARC. Информация, которую я перефразировал, находится в разделе «Унаследованные паттерны» этой главы. В ARC рекомендуется, чтобы IBOutlets было weak, если только они не являются верхним уровнем, и в этом случае они должны быть strong. Это означает, что вы полагаетесь на иерархию представлений (представления, сохраняющие свои подпредставления) для поддержания себя.

2 голосов
/ 02 ноября 2011

Я сообщил об ошибке в Apple, что если вы создадите переменные экземпляра IBOutlet вместо свойств, то Xcode по-прежнему будет автоматически создавать релизы в dealloc и т. Д. Приложения Xcode для iOS, похоже, всегда создают релизы для IBOutlet, независимо от того, верны они или нет.

Персонал Мне не нравится свойство IBOutlet, так как оно означает, что вы объявляете их как readwrite, что означает, что они документированы как readwrite, но в большинстве случаев (почти всегда) IBOutlet концептуально должен быть доступен только для чтения.Очевидно, что для первоначальной установки их необходимо перезаписать.

...