#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 сделает сохранение за вас.