Документы содержат довольно длинное объяснение того, почему Apple не хочет, чтобы вы это делали, и почему они явно не поддерживают это в Получение изменяемых объектов .Сводка такова:
Так что не принимайте решение об изменчивости объекта, основываясь на том, что самоанализ говорит вам об объекте.Относитесь к объектам как к изменяемым или не зависящим от того, что вы получили на границах API (то есть на основе типа возвращаемого значения).Если вам нужно однозначно пометить объект как изменяемый или неизменный при передаче его клиентам, передайте эту информацию как флаг вместе с объектом.
Я считаю их пример NSView наиболее простым для понимания, иэто иллюстрирует основную проблему Какао.У вас есть NSMutableArray с именем «elements», который вы хотите представить в виде массива, но не хотите, чтобы вызывающие абоненты связывались с ним.У вас есть несколько вариантов:
- Предоставить NSMutableArray как NSArray.
- Всегда делать неизменяемую копию при запросе
- Сохранять элементы как NSArray и создаватьновый массив каждый раз, когда он мутирует.
Я делал все это в разных точках.№ 1, безусловно, самое простое и быстрое решение.Это также опасно, так как массив может видоизменяться за спиной вызывающего.Но Apple указывает, что это то, что они делают в некоторых случаях (обратите внимание на предупреждение для -подвидов в NSView).Я могу подтвердить, что, хотя № 2 и № 3 намного безопаснее, они могут создавать серьезные проблемы с производительностью, поэтому, вероятно, именно поэтому Apple решила не использовать их на часто используемых членах, таких как -subviews.
Результатвсе это в том, что если вы используете # 1, то самоанализ будет вводить вас в заблуждение.У вас есть NSMutableArray, приведенный как NSArray, и самоанализ покажет, что он изменчив (самоанализ не может знать иначе).Но вы не должны мутировать его.Только проверка типа во время компиляции может сказать вам об этом, и поэтому это единственное, чему вы можете доверять.
Исправление для этого - это некая быстрая неизменяемая версия структуры изменяемых данных с копированием при записи.,Таким образом, # 2 может быть сделано с достойной производительностью.Я могу представить изменения в кластере NSArray, которые позволили бы это, но в настоящее время его нет в Какао (и может повлиять на производительность NSArray в обычном случае, сделав его не стартером).Даже если бы у нас было это, вероятно, существует слишком много кода, который полагается на текущее поведение, чтобы когда-либо позволять доверять интроспекции изменчивости.