使用sortUsingComparator的EXC_BAD_ACCESS

sun*_*nny 8 sorting exc-bad-access objective-c nsarray

我理解错误的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];
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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;
        }
    }];
Run Code Online (Sandbox Code Playgroud)

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


更多详情.我将NSComparator存储为

@property (strong, atomic) NSComparator sortWithThisComparator;
Run Code Online (Sandbox Code Playgroud)

All*_*len 1

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

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

因为您对线程问题的访问很差,所以我猜您没有在代码中很好地处理线程。

以下是一些建议:

  • NSMutableArray 不是线程安全的:我猜你把 self.items 操作放在异步线程中。如果我的说法是对的,请记住每次您想要编辑 self.items 时,请使用 NSLock 来保护它。

前任:

- (void)addItem:(id)item {
    dispatch_async(self.queue, ^{
        [threadLock lock];
        [self.items addObject:item];
        [threadLock unlock];
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 另一种是基于可变数组的排序:我认为这也很危险,因为可变数组不是线程安全的。

让我们看一下这一行:

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

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

NSArray *array = [self.items copy];
NSInteger newItemIndex = [array indexOfObject:item inSortedRange:NSMakeRange(0, [array count]) options:NSBinarySearchingInsertionIndex usingComparator:sortWithThisComparator];
Run Code Online (Sandbox Code Playgroud)
  • 此外,我发现 self.items.count 可能为零 而您正在制作一个NSMakeRange(0, self.items.count). 大概也修改一下函数中的条件 insertItem:
if (!sortWithThisComparator || self.items.count == 0) {}
Run Code Online (Sandbox Code Playgroud)

这些是我对这次运动的一些想法。一旦我得到其他可能性的想法,我会添加更多内容。