При разработке в AppKit, почему IB создает свойство, которое назначается, а не сохраняется? - программирование

При разработке в AppKit, почему IB создает свойство, которое назначается, а не сохраняется?

Я опытный разработчик iOS, и я решил попробовать свои силы в разработке AppKit. Есть несколько настроек, которые я делаю API-мудрой, но в остальном я нахожу разработку OS X, скажем так, "знакомой".

Я создавал пользовательские интерфейсы AppKit в Interface Builder и замечал, что когда я использую редактор WYSIWYG для создания свойств в своих файлах кода, Apple создает следующее:

@property (assign) IBOutlet NSTableView *tableView;

Я нахожу это очень любопытным, потому что способ делать вещи в iOS по умолчанию привел бы меня к этому:

@property (nonatomic, retain) IBOutlet NSTableView *tableView;

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

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

Почему Apple создает здесь слабую ссылку, а не сильную?

Я настраиваю себя на какие-то непреднамеренные последствия, используя сильные ссылки (но правильно выпуская в dealloc)? Есть ли какой-то шаблон, который мне не хватает?

4b9b3361

Ответ 1

Как владелец файла, вы должны владеть всеми и всеми объектами верхнего уровня в nib. Обычно вам не нужно владеть объектами внутри этих объектов, потому что родительский объект будет владеть его дочерними объектами; например, окно будет иметь свои представления.

AppKit nib loader неявно сохраняет все объекты верхнего уровня от имени владельца файла. (Это имело смысл до @property, синтезированных аксессуаров и ARC. ) Таким образом, даже если соответствующие свойства weak или unsafe_unretained (последний является синонимом для assign), владелец фактически владеет объектами верхнего уровня. И если вы идете в другую сторону и создаете эти свойства strong (a.k.a. retain), тогда FO имеет два владельца каждого объекта: неявное владение и собственность strong -property.

Предполагая, что вы используете ручной подсчет ссылок, вы можете освободить неявное право собственности в awakeFromNib, но это только что сделало работу. До тех пор, пока вы не замените какой-либо из этих объектов после загрузки ниба (например, замените вид таблицы для другого представления таблицы), свойство unsafe_unretained будет работать отлично, без лишнего сохранения или любой сделанной работы.

unsafe_unretained названо так (и это имя предпочтительнее, чем assign для свойств объекта) по какой-либо причине. Возвращая пример окна и его вида, предположим, что у вас есть окно и вы знаете об одном из его представлений. Представление viewview, вероятно, является его единственным владельцем, поэтому, когда вы закрываете окно (или пользователь закрывает его), представление будет выпущено и, следовательно, освобождено. Если ваше свойство в представлении unsafe_unretained/assign, вы все равно знаете об этом теперь мертвом объекте, и попытка отправить сообщение в представление может вызвать сбой или исключение.

Вам следует переключиться на ARC и объявить свойство как weak. Таким образом, не создается избыточное владение, и свойство автоматически будет установлено на nil, когда вид замирает, предотвращая возникновение сбоя чрезмерного выпуска.

(Если вы не владелец файла, ни одно из них не относится к вам, и вы должны, вероятно, объявить свои свойства по своему усмотрению. Либо weak, либо strong может быть хорошим выбором, в зависимости от того, как вы видите ваша иерархия владения и какой объект вы ссылаетесь.)

В iOS авторы UIKit вытащили теперь неявное сохранение. Вы должны написать свое собственное владение; если вы хотите владеть объектом из ниба или раскадровки, вы пишете свойство strong, и если вы имеете в виду только знать об этом, вы пишете weak или unsafe_unretained один, точно так, как вы ожидали.

TL; DR: Истерические причины.