Установка объектов на ноль во время быстрого перечисления

Я хочу установить для объекта значение «ноль» при перечислении массива следующим образом:

for(Object* object in array){
    object = nil;
}

Затем Xcode сообщает мне: «Переменные быстрого перечисления не могут быть изменены в ARC по умолчанию; объявите переменную __strong, чтобы разрешить это.

Что означает сделать это:

for(Object __strong* object in array){
    object = nil;
}

Это кажется излишним. Насколько я понимаю, объявление строгой ссылки на объект увеличивает его счетчик сохранения на единицу, а обнуление уменьшает счетчик удержания на единицу. Так как же мне установить объект в nil при перечислении через массив?

Я использую АРК.


person Fitzy    schedule 08.01.2013    source источник
comment
Что ты пытаешься здесь сделать? Установка переменной цикла в nil бессмысленна. Если вы хотите очистить память, установите массив в nil или удалите все объекты из массива.   -  person rmaddy    schedule 08.01.2013
comment
Однако удаление объектов из массива не обязательно приводит к удалению объектов, не так ли?   -  person Fitzy    schedule 08.01.2013
comment
Что вы подразумеваете под удалением объектов? Удаление их из массива уменьшает количество сохранений. Если больше ничего не удерживает объект, он будет освобожден.   -  person rmaddy    schedule 08.01.2013
comment
Пожалуйста, объясните свою большую цель более четко, потому что путь, который вы используете для ее достижения, наверняка неправильный.   -  person jscs    schedule 08.01.2013
comment
Я пытаюсь освободить память, в которой хранится каждый объект в массиве. Просто вызывая removeAllObjects для массива, я не знаю точно, освобождается ли память, так как я не совсем уверен, что объекты ссылаются где-то еще.   -  person Fitzy    schedule 08.01.2013
comment
Во-первых, пытаться заставить другие, неизвестные объекты потерять право собственности на объект — очень плохая идея. Во-вторых, под ARC, я не думаю, что вы не можете это сделать. Если вы хотите, чтобы объекты исчезли, а массив сохранил их, освободите массив или используйте removeAllObjects. Пусть другие объекты, которым нужно содержимое массива, сами занимаются управлением своей памятью.   -  person jscs    schedule 08.01.2013
comment
АА, вижу. Большое спасибо за помощь, если бы вы превратили это в ответ, я бы его принял.   -  person Fitzy    schedule 08.01.2013


Ответы (3)


См. Переменные итерации быстрого перечисления в Clang "Цель- C Автоматический подсчет ссылок» документация:

Если переменная объявлена ​​в условиях цикла быстрого перечисления Objective-C и переменная не имеет явного квалификатора владения, то она уточняется с помощью const __strong, а объекты, встречающиеся во время перечисления, фактически не сохраняются.

Обоснование
Такая оптимизация стала возможной, поскольку быстрые циклы перечисления обещают сохранить объекты во время перечисления, а сама коллекция не может быть синхронно изменена. Его можно переопределить, явно указав переменную с помощью __strong, что сделает переменную снова изменяемой и заставит цикл сохранять объекты, с которыми он сталкивается.

Таким образом, по умолчанию переменная цикла неизменяема, а счетчик сохранения текущего объекта не увеличивается из соображений производительности.

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

person Martin R    schedule 08.01.2013
comment
Итак, как я и думал, излишне объявлять сильную ссылку на объект, а затем устанавливать ее в nil. Так как же тогда освободить память объектов в массиве? Вызов removeAllObjects для массива не обязательно означает, что объект больше не содержит строгой ссылки, поскольку на него могут ссылаться другие объекты. - person Fitzy; 08.01.2013
comment
@dreamlax да, так что я собрал. Я все еще привыкаю к ​​управлению памятью; Я слишком долго закрывал на это глаза.... - person Fitzy; 08.01.2013
comment
@Fitzy: Так как же тогда освободить память объектов в массиве? - Вы не можете, как объяснили Рамди и Джош Касвелл. Установка строгой ссылки на nil не является заменой dealloc (что запрещено ARC), она просто уменьшает количество сохраняемых объектов. Объект будет освобожден, когда исчезнет последняя сильная ссылка. - person Martin R; 08.01.2013

Ярлык:

[array removeAllObjects];

Если вы хотите, чтобы ваш массив по-прежнему содержал x элементов, но не элементы, которые в данный момент находятся в нем, вы можете использовать заполнитель NSNull:

for (NSUInteger i = 0; i < [array count]; i++)
    [array replaceObjectAtIndex:i withObject:[NSNull null]];

Помните, что массив содержит только ссылки на свои объекты. Управление памятью сработает и освободит объекты, если массив больше не содержит ссылки на них (но только если ничего больше не делает).

person dreamlax    schedule 08.01.2013

В комментариях вы показали, что ваше намерение здесь состоит в том, чтобы освободить объекты, которые находятся в массиве, независимо от того, имеет ли что-то еще право собственности на них. Это нарушение основного принципа управления памятью: вы не должны освобождать память, которой не владеете. Это Плохая Идея делать то, что вы хотите делать.

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

Есть две вещи, которые вам разрешено делать с точки зрения этого массива. Вы можете освободить массив целиком, что откажется от претензий массива на содержащиеся в нем объекты; если они не принадлежат никому другому, они будут освобождены. Если вы хотите сохранить сам массив, но освободить все его элементы, используйте removeAllObjects; опять же, элементы будут освобождены, если они никому не принадлежат.

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

person jscs    schedule 10.01.2013