使用sortUsingComparator的EXC_BAD_ACCESS

时间:2016-02-03 12:23:02

标签: objective-c sorting nsarray exc-bad-access

我理解错误EXC_BAD_ACCESS的含义一般,但我对我的情况发生的事情感到困惑。

我有一个自定义类,其NSComparator属性sortWithThisComparator。如果该属性是由用户设置的,当我将项插入实例的类属性数组items时,我使用比较器来确定插入位置:

- (void) insertItem:(id<NSCoding, CKArchivingItem>) item {
    if (arrayObjectClassString && ![item isKindOfClass:NSClassFromString(arrayObjectClassString)]) {
        [NSException raise:@"YOU MADE A MISTAKE" format:@"you tried to insert a %@ but I can only accept %@", [item class], arrayObjectClassString];
    } else {
        if (!sortWithThisComparator) {
            [self.items addObject:item];
        } else {
            NSInteger newItemIndex = [self.items indexOfObject:item inSortedRange:NSMakeRange(0, [self.items count]) options:NSBinarySearchingFirstEqual usingComparator:sortWithThisComparator];
            if (newItemIndex >= [self.items count]) {
                [self.items addObject:items];
            } else {
                [self.items insertObject:item atIndex:newItemIndex];
            }
        }
    }
}

当我没有设置比较器时,一切正常,但是当我使用比较器时,我得到一个错误的访问错误:

typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);

...
   [[CKGenericSingletonSubclass sharedManager] setSortWithThisComparator: ^NSComparisonResult(CKGeneralizedItemSubclass *i1, CKGeneralizedItemSubclass *i2) {
        NSLog(@"we are inside");
        NSLog(@"here is the item 1 %@", i1);
        NSLog(@"we are comparing this float %f to thisf loat %f", i1.gradeSchoolAverage, i2.gradeSchoolAverage);
        if (i1.gradeSchoolAverage < i2.gradeSchoolAverage) {
            return NSOrderedAscending;
        } else if (i1.gradeSchoolAverage == i2.gradeSchoolAverage) {
            return NSOrderedSame;
        } else {
            return NSOrderedDescending;
        }
    }];

我在比较器的第二行遇到一个错误的访问线程,它只是记录通过NSComparator传递的一个参数。然而我传递给insertItem的类实例可以在其他地方访问而没有这个问题,所以我知道它们已经被正确地实例化并且正确地通过了,因为我可以将它们插入到items属性中而没有比较。我在这里缺少什么?

更多细节。我将NSComparator存储为

@property (strong, atomic) NSComparator sortWithThisComparator;

2 个答案:

答案 0 :(得分:1)

实际上,我只能根据你上面提到的代码做出一些假设。

对于第一个块,我猜self.items是一个可变数组。同样在函数insertItem:中,一旦sortWithThisComparator不为nil,在排序过程获得索引后将插入新对象。

由于您在线程问题上获得了不良访问权限,因此我猜您在代码中没有很好地处理线程问题。

以下是一些建议:

  • NSMutableArray不是线程安全的:我想你放了self.items 在异步线程中操作。如果我对此有所了解,请记住每次要编辑self.items时,请使用NSLock 保护它。

例如:

- (void)addItem:(id)item {
    dispatch_async(self.queue, ^{
        [threadLock lock];
        [self.items addObject:item];
        [threadLock unlock];
    }
}
  • 另一个是基于可变阵列的排序:我觉得它很危险 因为可变数组不是线程安全的。

让我们来看看这一行:

NSInteger newItemIndex = [self.items indexOfObject:item inSortedRange:NSMakeRange(0, [self.items count]) options:NSBinarySearchingFirstEqual usingComparator:sortWithThisComparator];

在我看来,我会首先进行数组复制并使用NSBinarySearchingInsertionIndex设置选项:

NSArray *array = [self.items copy];
NSInteger newItemIndex = [array indexOfObject:item inSortedRange:NSMakeRange(0, [array count]) options:NSBinarySearchingInsertionIndex usingComparator:sortWithThisComparator];
  • 此外,我发现了self.items.count可能存在的情况 归零,您正在制作NSMakeRange(0, self.items.count)。 可能还会在功能上略微修改条件 insertItem:
if (!sortWithThisComparator || self.items.count == 0) {}

这些是我在这场运动中的一些想法。一旦我得到其他可能性的想法,我就会添加更多。

答案 1 :(得分:0)

我猜测的问题是使用sortWithThisComparator作为变量而不是属性。尝试将sortWithThisComparator替换为self.sortWithThisComparator让我知道是否有帮助