Ios NSArrayM在枚举时发生了变异-添加对象,而不是删除对象

Ios NSArrayM在枚举时发生了变异-添加对象,而不是删除对象,ios,objective-c,arrays,Ios,Objective C,Arrays,我试图查看StackOverflow上的所有这些问题,但找不到任何对我有帮助的东西。我甚至不能自己复制它,我是通过iTunes Connect从实际用户那里得到的。以下是Xcode上的崩溃日志: 这是我的完整serializedLocations方法,正在崩溃,没有从中剥离任何内容: - (NSMutableArray *)serializedLocations:(NSArray *)locations withTimestamp:(NSInteger)timestamp{ NSMut

我试图查看StackOverflow上的所有这些问题,但找不到任何对我有帮助的东西。我甚至不能自己复制它,我是通过iTunes Connect从实际用户那里得到的。以下是Xcode上的崩溃日志:

这是我的完整serializedLocations方法,正在崩溃,没有从中剥离任何内容:

- (NSMutableArray *)serializedLocations:(NSArray *)locations withTimestamp:(NSInteger)timestamp{
    NSMutableArray *serializedLocations = [NSMutableArray new];

    if(locations){
        for (CLLocation *location in locations) {
            NSInteger locationTimeInterval = floor([location.timestamp timeIntervalSince1970] * 1000);
            NSInteger t = locationTimeInterval - timestamp;
            NSMutableDictionary *serializedLocation = [NSMutableDictionary new];
            serializedLocation[@"x"] = [NSNumber numberWithDouble:location.coordinate.latitude];
            serializedLocation[@"y"] = [NSNumber numberWithDouble:location.coordinate.longitude];
            serializedLocation[@"a"] = [NSNumber numberWithDouble:location.horizontalAccuracy];
            serializedLocation[@"v"] = [NSNumber numberWithDouble:location.speed];
            serializedLocation[@"o"] = [NSNumber numberWithDouble:location.course];
            serializedLocation[@"t"] = [NSNumber numberWithLong:t];
            [serializedLocations addObject:serializedLocation];
        }
    }
    return serializedLocations;
}
我似乎找不到缺陷

  • 我正在创建一个临时新阵列
  • 我不会更改正在枚举的数组
  • 我正在向临时数组添加新对象
  • 我将返回新的临时数组
编辑:

让所有其他方法运行的父级调用如下:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [ApiClient insertEvent:event withLocations:locations];
    });

我猜想,
位置
,虽然在这里键入的是NSArray,但实际上是一个NSMutableArray-这就是在枚举它时正在变异的数组。如果要在后台线程上运行此代码,则需要确保
位置
不会在“背后”发生变异。一种简单的方法是在调用站点制作
位置的深度副本,并传递该副本,而不是可变数组。(请注意,在
serializedLocations:withTimestamp:
中进行深度复制是不够的,因为
位置在复制过程中可能会发生变异。)

我猜
位置
,尽管在这里键入的是NSArray,实际上是一个NSMutableArray—这就是在枚举它时发生变化的数组。如果要在后台线程上运行此代码,则需要确保
位置
不会在“背后”发生变异。一种简单的方法是在调用站点制作
位置的深度副本,并传递该副本,而不是可变数组。(请注意,在
serializedLocations:withTimestamp:
中进行深度复制是不够的,因为
位置在复制过程中可能会发生变异。)

但它发生在后台线程上?如果
位置
本身是可变的怎么办?当背景线程持有对它的引用时,如果它被其他东西变异了呢?我没有看到你在这里做任何事情来保证代码的线程安全。是的,它发生在后台线程上。是否愿意分享如何使这段代码线程安全?我是否应该创建一个位置副本并枚举该副本,而不是?“共享”是全部问题。您不想共享
位置
。至少,首先,为什么不把它复制一份呢哦,我看到我打字的时候,你想到了!:):D谢谢@matt我现在就自己动手吧。如果你想做出正确的回答,我很乐意选择。谢谢但它是在后台线程上发生的?如果
位置
本身是可变的怎么办?当背景线程持有对它的引用时,如果它被其他东西变异了呢?我没有看到你在这里做任何事情来保证代码的线程安全。是的,它发生在后台线程上。是否愿意分享如何使这段代码线程安全?我是否应该创建一个位置副本并枚举该副本,而不是?“共享”是全部问题。您不想共享
位置
。至少,首先,为什么不把它复制一份呢哦,我看到我打字的时候,你想到了!:):D谢谢@matt我现在就自己动手吧。如果你想做出正确的回答,我很乐意选择。谢谢哦,我正要这么做。没有意识到它可能在“复制过程中”发生变异。我知道这不是这个问题的主题,但有没有一种方法可以真正测试它呢?我们在这里讨论的是多线程!假设一件事不会发生真的是个坏主意。总是做最坏的打算。毕竟,没有做到这一点是你陷入困境的原因;您正在跨线程任意共享一个可变对象。这从一开始就是一个糟糕的设计;幸运的是,问题以如此清晰的形式出现,甚至可以猜测原因。通常情况下,线程问题比实际错误要晚得多。我建议您立即回顾所有代码,并寻找其他多线程的位置。没有意识到它可能在“复制过程中”发生变异。我知道这不是这个问题的主题,但有没有一种方法可以真正测试它呢?我们在这里讨论的是多线程!假设一件事不会发生真的是个坏主意。总是做最坏的打算。毕竟,没有做到这一点是你陷入困境的原因;您正在跨线程任意共享一个可变对象。这从一开始就是一个糟糕的设计;幸运的是,问题以如此清晰的形式出现,甚至可以猜测原因。通常情况下,线程问题比实际错误要晚得多。我建议您立即回顾所有代码,并寻找其他多线程位置。