Я знаю, что в этом посте есть похожие посты, но пока я ничего не нашел, чтобы решить мою проблему. Я получаю данные из API через JSON и сохраняю их, а затем отображаю данные в пользовательском интерфейсе через извлечение базовых данных после сохранения. Это происходит примерно через каждые 100 или около того поисков (вызовов API). Число от 1 до 100 является случайным. Иногда это каждые 20 поисков и т. Д. Новые установки приложения, кажется, имеют эту проблему больше.
Exception was caught during Core Data change processing. This is
usually a bug within an observer of
NSManagedObjectContextObjectsDidChangeNotification. *** Collection
<__NSCFSet: 0x6000030e7f60> was mutated while being enumerated. with
userInfo (null)
CoreData: error: Serious application error. Exception was caught during
Core Data change processing. This is usually a bug within an observer
of NSManagedObjectContextObjectsDidChangeNotification. *** Collection
<__NSCFSet: 0x6000030e7f60> was mutated while being enumerated. with
userInfo (null)
2018-06-30 12:51:36.264733-0600 [7055:6252340] ***
Terminating app due to uncaught exception 'NSGenericException', reason:
'*** Collection <__NSCFSet: 0x6000030e7f60> was mutated while being
enumerated.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010d829f66 __exceptionPreprocess + 294
1 libobjc.A.dylib 0x000000010c8f904d objc_exception_throw + 48
2 CoreFoundation 0x000000010d826c6c __NSFastEnumerationMutationHandler + 124
3 CoreData 0x000000010d1baf28 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processDeletedObjects:] + 328
4 CoreData 0x000000010d1a529d -[NSManagedObjectContext(_NSInternalChangeProcessing) _propagatePendingDeletesAtEndOfEvent:] + 109
5 CoreData 0x000000010d1a028a -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 1034
6 CoreData 0x000000010d1790ff _performRunLoopAction + 335
7 CoreFoundation 0x000000010d78cea7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
8 CoreFoundation 0x000000010d7872de __CFRunLoopDoObservers + 430
9 CoreFoundation 0x000000010d787981 __CFRunLoopRun + 1553
10 CoreFoundation 0x000000010d787031 CFRunLoopRunSpecific + 625
11 GraphicsServices 0x0000000110d35136 GSEventRunModal + 62
12 UIKitCore 0x0000000116098839 UIApplicationMain + 140
13 AppNameHere 0x00000001063c7234 main + 68
14 libdyld.dylib 0x000000010eed2a61 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
2018-06-30 12:51:36.271149-0600 [7055:6255838] [Assert]
Cannot be called with asCopy = NO on non-main thread.
Опубликован некоторый упрощенный код (для упрощения прочтения здесь удалены некоторые вещи, не относящиеся к CoreData. Я уже знаю, что большая часть этого кода - дурной тон, однако это моя лучшая работа и трудолюбие.
//globalVariable declared:
let appDelegate = UIApplication.shared.delegate as? AppDelegate
//in AppDelegate:
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "AppName")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
//in VC:
let downloadAirports = DownloadAirports()
let initialAirportDownload = defaults.bool(forKey: "initialAirportDownload")
if initialAirportDownload == false {
self.showAirportDownloadingAlert(show: true)
self.downloadAirports.getAirports(completion: {
DispatchQueue.main.async {
print("finishedDownloadingAirports")
self.defaults.set(true, forKey: "initialAirportDownload")
self.showAirportDownloadingAlert(show: false)
})
}
}
//in DownloadAirports class:
struct AirportsJSON : Decodable {
let airports : [AirportJSON]
}
struct AirportJSON : Decodable {
let iata : String?
let airportName : String?
let countryCode : String?
let utcOffset : Int?
let classification : Int?
}
func getAirports(completion: @escaping () -> ()) {
let serverAddress = ServerAccess.serverAddress
let jsonUrlString = "\(serverAddress)"
guard let url = URL(string: jsonUrlString) else {
return
}
deleteAirports()
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else {
return
}
do {
let airports = try JSONDecoder().decode(AirportsJSON.self, from: data)
guard let moc = appDelegate?.persistentContainer.viewContext else {
return
}
var i = 0
while i < airports.airports.count {
self.saveAirport(airports: airports.airports[i], moc: moc)
i += 1
}
} catch let jsonErr {
print(jsonErr)
}
completion()
}.resume()
guard let moc = appDelegate?.persistentContainer.viewContext else {
return
}
do {
try moc.save()
} catch {
debugPrint(error.localizedDescription)
}
}
func saveAirport(airports : AirportJSON, moc : NSManagedObjectContext) {
var searchString = ""
let airport = Airports(context: moc)
if let iata = airports.iata {
if let name = airports.airportName {
searchString = "\(iata) - \(name)"
airport.searchString = searchString
airport.iata = iata
print(iata)
}
}
if let classification = airports.classification {
airport.classification = Int16(classification)
}
if let timeZone = airports.utcOffset {
airport.timeZone = Int16(timeZone)
}
if let countryCode = airports.countryCode {
airport.countryCode = countryCode
}
}
func deleteAirports() {
guard let moc = appDelegate?.persistentContainer.viewContext else {
return
}
let fetchRequest : NSFetchRequest<Airports> = Airports.fetchRequest()
do {
let airports = try moc.fetch(fetchRequest)
for airport in airports {
moc.delete(airport)
}
do {
try moc.save()
} catch {
print(error.localizedDescription)
}
} catch {
print(error)
}
}