Удаление объекта из NSmutableArray

Я наткнулся на следующий ярлык при настройке цикла for (ярлык по сравнению с примерами из учебника, которые я использовал):

for (Item *i in items){ ... }

В отличие от более длинного формата:

for (NSInteger i = 0; i < [items count]; i++){ ... } //think that's right

Если я использую более короткую версию, есть ли способ удалить элемент, который в настоящее время повторяется (например, «i»)? Или мне нужно использовать более длинный формат?


person Ben Packard    schedule 03.05.2010    source источник
comment
Первый цикл for известен как расширенный цикл FOR, а второй — старый стандартный цикл FOR. Я узнал об этом, когда проходил сертификацию по Java.   -  person Popeye    schedule 11.08.2012
comment
Если вам действительно нужно удалить элементы из массива во время его итерации, и вы не можете удалить их впоследствии, используя removeObjectsInArray: или removeObjectsAtIndexes:, как предложил @Vladimir, вы всегда можете выполнить итерацию по копии исходного массива.   -  person Tiago    schedule 04.08.2014


Ответы (5)


Вы не можете удалять объекты из массива во время быстрого перечисления это:

нумерация «безопасна» — перечислитель имеет защиту от мутаций, так что если вы попытаетесь изменить коллекцию во время перечисления, возникнет исключение.

В любом случае, зачем вам менять контейнер при его перечислении? Рассмотрите возможность хранения элементов, которые необходимо удалить, и удалите их из контейнера с помощью метода removeObjectsInArray: или removeObjectsAtIndexes:.

person Vladimir    schedule 03.05.2010
comment
Спасибо. Я меняю его при перечислении, потому что это временная очередь. Я перемещаю все элементы в другой массив. - person Ben Packard; 03.05.2010
comment
Если вы перемещаете все объекты в другой массив, попробуйте следующее: [destinationArray addObjectsFromArray: sourceArray]; [sourceArray removeAllObjects]; - person JeremyP; 04.05.2010
comment
Отличный ответ! Работает как шарм! - person Groot; 27.11.2012

Просто добавьте ключевое слово break; после удаления элемента...

for(id item in items) {
    if([item isEqual:itemToDelete]) {
        [items removeObject:item];
        break;
    }
}
person RaiderF    schedule 13.10.2011
comment
@Abdullah71 с идентификатором, который вы никогда не используете *. - person rptwsthi; 05.07.2013
comment
Это приведет к удалению одного объекта и остановке итерации, что приведет к пропуску возможных других объектов, которые следует удалить. Поэтому используйте это только в том случае, если вам нужно удалить от нуля до одного объекта за итерацию. - person marsbear; 18.08.2016

Коллекция Objective-C не должна изменяться во время перечисления.

Вы можете использовать этот вариант для удаления объектов из коллекции:

for (NSInteger i = items.count - 1; i >= 0 ; i--) {
   [items removeObjectAtIndex:i];
}
person serhii    schedule 03.09.2015
comment
Imho самый короткий способ сделать это правильно, учитывая, что с вашей бизнес-логикой все в порядке, чтобы пройти массив сзади вперед. - person marsbear; 18.08.2016

Первый цикл — это цикл «для каждого» в Objective C.

*i — указатель на прямой элемент в массиве элементов (чаще всего это будет NSMutableArray).

Таким образом, вы можете работать непосредственно с элементом:

[items removeObject: i];

Это (должно) работать - в настоящее время я не работаю на своем Mac и не могу это проверить. Однако может случиться так, что Objective-C предотвращает удаление объектов при переборе коллекции (что довольно часто встречается в большинстве языков).

person BergmannF    schedule 03.05.2010
comment
Действительно, вы не можете удалить (или видоизменить) NSMutableArray во время его перечисления, поэтому вызов removeObject: вызовет исключение. (как объяснил Владимир в своем ответе) - person Nick Forge; 03.05.2010

Я использую этот код для этого:

for (NSUInteger i = [items count] - 1; ; i--) {
     [items removeObjectAtIndex:i];
}
person slava    schedule 05.10.2015
comment
Только пока я не получу -1... тогда он вылетает :) - person marsbear; 18.08.2016