Поэтому я получаю эту ошибку, когда сохраняю данные ядра.
Coredata [21468: 13173906] [ошибка]: ошибка: SQLCore dispatchRequest: запрос обработки исключительной ситуации: ** определена только ** -_referenceData64 для абстрактного класса. Определить - [NSTevenObjectID_default _referenceData64]! с userInfo (ноль)
Я недавно закончил курс по основным данным, преподаватель немного по топи c говорит, что данные ядра не являются поточно-ориентированными. Итак, он предложил дочерний / родительский контекст, поэтому я пытался сделать это, но продолжал получать ошибку сверху. Вот как выглядит мой код.
struct Service {
static let shared = Service()
func downloadPokemonsFromServer(completion: @escaping ()->()) {
let urlString = "https://pokeapi.co/api/v2/pokemon?limit=9"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let err = error {
print("Unable to fetch pokemon", err)
}
guard let data = data else { return }
let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateContext.parent = CoreDataManager.shared.persistentContainer.viewContext
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let pokemonJSON = try decoder.decode(PokemonsJSON.self, from: data)
pokemonJSON.pokemons.forEach { (JSONPokemon) in
//Works fine with privateContext here
let pokemon = Pokemon(context: privateContext)
pokemon.name = JSONPokemon.name
pokemon.url = JSONPokemon.detailUrl
}
//Why does the privateContext work here
//and doesn't crash my app.
try privateContext.save()
try privateContext.parent?.save()
completion()
} catch let err {
print("Unable to decode PokemonJSON. Error: ",err)
completion()
}
}.resume()
}
func fetchMoreDetails(pokemon: Pokemon, urlString: String, context: NSManagedObjectContext, completion: @escaping ()->()) {
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let err = error {
print("Unable to get more details for pokemon", err)
}
guard let data = data else { return }
let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateContext.parent = CoreDataManager.shared.persistentContainer.viewContext
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let pokemonDetailJSON = try decoder.decode(PokemonDetailJSON.self, from: data)
pokemonDetailJSON.types.forEach { (nestedType) in
// I can just change this to context and it works
// Why doesnt it work with privateContext and crashes my app
let type = Type(context: privateContext)
type.name = nestedType.type.name
pokemon.addToTypes(type)
}
try privateContext.save()
try privateContext.parent?.save()
completion()
} catch let err {
print("Unable to decode pokemon more details", err)
completion()
}
}.resume()
}
}
Итак, в downloadPokemonsFromSever я вызываю API, который анализирует json и сохраняет его в Coredata. Я следовал инструкциям моего инструктора, создавая privateContext и затем устанавливая его родителя в свой mainContext. Затем я создаю нового покемона с именем и URL-адресом, используя мой privateContext, а НЕ mainContext. Когда я полностью разбираю своего покемона I go в другой API, в котором есть более подробная информация об этом покемоне.
Вот где мое приложение начинает создавать sh. Как вы можете видеть из fetchMoreDetails, есть параметр, который является контекстом. Когда я пытаюсь создать новый тип с privateContext, это приводит к сбою моего приложения. Когда я использую контекст, который передается через него, работает нормально. Я хотел бы знать, почему privateContext работает внутри downloadPokemonFromServer, а не в fetchMoreDetails. Я оставил комментарий над строкой, которая, по моему мнению, вылетает из моего приложения. Вот как я называю это в моем ViewController, используя это действие.
@objc func handleRefresh() {
Service.shared.downloadPokemonsFromServer {
let context = CoreDataManager.shared.persistentContainer.viewContext
self.pokemonController.fetchedObjects?.forEach({ (pokemon) in
Service.shared.fetchMoreDetails(pokemon: pokemon, urlString: pokemon.url ?? "", context: context) {
}
})
}
tableView.refreshControl?.endRefreshing()
}