Добавление объекта в NSMutableArray вызывает сбой

#ios #crash #nsmutablearray #sigabrt #cgrect

#iOS #сбой #nsmutablearray #sigabrt #cgrect

Вопрос:

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

Вот код в touchesBegan, точка блокировки — это точка касания экрана

 for (NSValue *val in rectangleArray){
    CGRect rectangle = [val CGRectValue];
    if (CGRectContainsPoint(rectangle, blockPoint)) {
        CGRect newRectangle;
        CGRect addRectangle;
        if (!inLandscape) {
            newRectangle = CGRectMake(rectangle.origin.x, rectangle.origin.y, rectangle.size.width, blockPoint.y - rectangle.origin.y);
            addRectangle = CGRectMake(rectangle.origin.x, blockPoint.y, rectangle.size.width, rectangle.size.height - (blockPoint.y - rectangle.origin.y));

        }
        else {
            newRectangle = CGRectMake(rectangle.origin.x, rectangle.origin.y, blockPoint.x - rectangle.origin.x, rectangle.size.height);
            addRectangle = CGRectMake(blockPoint.x, rectangle.origin.y, rectangle.size.width - (blockPoint.x - rectangle.origin.x), rectangle.size.height);
        }
        [rectangleArray replaceObjectAtIndex:[rectangleArray indexOfObject:val] withObject:[NSValue valueWithCGRect:newRectangle]];
        [rectangleArray addObject:[NSValue valueWithCGRect:addRectangle]];
    }
}
  

Почему это сбой?

Комментарии:

1. При сбое в консоли почти всегда появляются сообщения. Вы должны включить их в свой пост.

Ответ №1:

Вы пытаетесь изменить массив (с помощью «replaceObjectAtIndex:») при его перечислении («цикл for» в начале вашего кода). Это вызывает исключение. Вы должны увидеть это в журнале консоли, что-то вроде этого:

Завершение работы приложения из-за неперехваченного исключения 'NSGenericException', причина: '*** Коллекция была изменена во время перечисления.

Вместо этого вы можете сначала перечислить, затем определить объекты, которые вы хотите изменить, сохранить их в другом классе коллекции (NSSet или другом NSArray) и, наконец, применить собранные элементы в исходном массиве. Или другая возможность заключается в том, что вы создаете копию первого массива, затем перечисляете копию и вносите изменения в исходный массив.

Комментарии:

1. [rectangleArray AddObject:[NSValue valueWithCGRect:addRectangle]]; также приведет к сбою. Просто оказывается, что происходит сбой, прежде чем он доберется до этой части

2. по той же причине: вы не можете изменить изменяемый массив во время его перечисления; это исключение, которое создается средой выполнения для сохранения целостности коллекции.

Ответ №2:

У меня была эта проблема раньше в моем коде, и позвольте мне угадать, вы создали массив в своем методе init or initWith.... , верно?

Чтобы правильно создать свойство с помощью кода (то есть не элемента управления пользовательского интерфейса из Interface Builder) в init методе, всегда сохраняйте свое свойство.

Короче говоря,

 myNSMutableArray = [[NSMutableArray alloc] initWith....];
  

должно быть

 myNSMutableArray = [[[NSMutableArray alloc] initWith....] retain];
  

таким образом, даже если ваш init метод завершится, количество сохранений myNSMutableArray не позволит системе освободить ваш объект.

В качестве альтернативы, поскольку вы объявляете свойство (сохраняете), вы можете использовать

 self.myNSMutableArray = [[NSMutableArray alloc] initWith...];
  

Использование accessor сделает сохранение за вас.