【问题标题】:Adding object to NSMutableArray causing crash将对象添加到 NSMutableArray 导致崩溃
【发布时间】:2011-11-05 21:59:12
【问题描述】:

我正在创建一个以屏幕大小的 CGRect 开头的应用程序。当用户触摸 CGRect 内部时,它被切割成两个 CGRect。当我触摸创建的新 CGRect 内部时,我可以正常工作,但是当我触摸不是最新添加到 rectangleArray 的 CGRect 内部时,应用程序崩溃并显示 sigabrt。

这里是touchesBegan中的代码,blockPoint是屏幕被触摸的点

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]];
    }
}

为什么会崩溃?

【问题讨论】:

  • 发生崩溃时,控制台中几乎总是有消息。您应该在帖子中包含这些内容。

标签: ios crash nsmutablearray sigabrt cgrect


【解决方案1】:

您试图在枚举数组(代码开头的“for 循环”)时改变数组(使用“replaceObjectAtIndex:”)。这引发了一个例外。您应该在控制台日志中看到它,如下所示:

由于未捕获的异常“NSGenericException”而终止应用程序,原因:“*** Collection 在枚举时发生了变异。

您可以做的是首先枚举,然后识别您想要变异的对象,将它们存储在另一个集合类(NSSet 或另一个 NSArray)中,最后将收集的项目应用到原始数组中。 或者另一种可能性是您复制第一个数组,然后枚举副本并对原始数组进行更改。

【讨论】:

  • [rectangleArray addObject:[NSValue valueWithCGRect:addRectangle]];会很好地导致崩溃。事实证明它在到达那部分之前就崩溃了
  • 同样的原因:你不能在枚举的时候改变一个可变数组;这是一个由运行时环境引发的异常,以保持集合的完整性。
【解决方案2】:

我之前在代码中遇到过这个问题,让我猜猜,你已经在 init 或 initWith.... 方法中创建了数组,对吧?

要在init 方法中使用代码正确创建属性(即不是来自 Interface Builder 的 UI 控件),始终保留您的属性。

总之,

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

应该是

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

这样,即使您的init 方法结束,myNSMutableArray 的保留计数也会阻止系统释放/释放您的对象。

另外,由于您以(保留)方式声明属性,因此您可以使用

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

使用访问器将为您执行保留。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多