2017-04-03 30 views
0

我試着在StackOverflow上查找所有這些問題,並找不到任何幫助我的東西。我甚至無法自己複製它,我通過iTunes Connect從實際用戶那裏得到了這一點。這是在Xcode中的崩潰日誌:NSArrayM被枚舉時發生了變異 - 添加對象,而不是刪除

Alt text

這是我的全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]; 
    }); 
+3

但它發生在後臺線程?如果'locations'本身是可變的呢?而如果這個後臺線程持有對它的引用,它會被別的東西改變呢?我沒有看到你在這裏做任何事情來使這個代碼是線程安全的。 – matt

+0

是的,它發生在後臺線程上。謹慎分享我可以如何使這段代碼線程安全? – Jan

+0

我應該只是創建一個位置的副本,並枚舉該副本? – Jan

回答

2

我猜locations ,雖然在這裏鍵入的是一個NSArray,實際上是一個NSMutableArray - 並且這個是在列舉它時正在進行變異的數組。如果您要在後臺線程上運行此代碼,則需要確保locations未被「背後」突變。一個簡單的方法就是在呼叫站點做一個locations的深層拷貝,並通過那個而不是可變數組。 (請注意,這是不夠的在這裏做的深層副本在serializedLocations:withTimestamp:,爲locations可以在副本過程中突變

+0

哦,我正要這樣做。沒有意識到它可能會在「複製過程中」發生變異。我知道這是關於這個問題的主題,但有沒有一種方法可以真正測試這個問題? – Jan

+1

我們在這裏討論多線程!假設一件事情不可能發生是一個壞主意。總是假設最糟糕的。畢竟,不這樣做是因爲你陷入了這個混亂局面;你正在肆意分享跨線程的可變對象。這從一開始就是糟糕的設計;你很幸運,這個問題以這種清晰的形式出現,甚至有可能導致原因。更通常的情況是,線程問題會比實際的錯誤晚得多。我建議你立即回顧所有的代碼並尋找其他多線程的地方。 – matt

相關問題