Для приватных полей - я предлагаю использовать прямые ивары безопасно только для примитивных типов (BOOL / int / float и т. Д.). Я считаю хорошей практикой обертывание всего , связанного с управлением памятью, в свойствах - даже редко используемых полей. Дополнительным преимуществом этого подхода является то, что IDE обычно выделяет прямой доступ к иварам по-разному, поэтому у вас всегда есть хорошее разделение простых скалярных полей и полей типа объекта.
В противоположность этому, я бы настоятельно не рекомендовал бы любые прямые ivars в классе public interface . Из-за динамической природы языка это может привести к ошибкам во время выполнения, которые чрезвычайно сложно найти, локализовать и исправить. Рассмотрим следующую иерархию
@interface BaseControl
...
@end
@interface Label : BaseControl
...
@end
@interface Button : BaseControl {
@public
BOOL enabled;
}
@end
и фрагмент кода
- (void)enableAllButtons {
NSArray *buttons = [self getAllButtons]; // expected to contain only Button instances
for (Button *button in buttons) {
button->enabled = YES;
}
}
Теперь представьте, что где-то в логике -getAllButtons есть ошибка, и вы также получите некоторые Label, возвращенные в этом массиве - так что этим экземплярам класса Label будет присвоен пропущенный ivar. Факт, который может быть удивительным, заключается в том, что -enableAllButtons не будет аварийно завершать работу в этом случае. Но в этот момент внутренняя структура этих экземпляров Label повреждена , и это вызовет непредсказуемое поведение и вылетит при их использовании в других местах.
Как и некоторые популярные проблемы с управлением памятью (и вообще - с висячими указателями) - такие проблемы трудно найти и локализовать - потому что появление ошибки обычно является отдаленным (с точки зрения времени, кода или потока приложения) ) с места, вызвавшего ошибку. Но с этой конкретной проблемой у вас даже нет удобных инструментов (таких как анализаторы утечек / зомби и т. Д.), Которые помогли бы вам локализовать и исправить это - даже когда вы научитесь воспроизводить его и сможете легко изучить ошибочное состояние.
Очевидно, что если вы используете @property (assign) BOOL enabled;
, вы получите простую диагностику и исправление исключения времени выполнения в -enableAllButtons.