Сохранить данные JSON в CoreData - PullRequest
0 голосов
/ 06 ноября 2019

Я хочу загрузить JSON из API и сохранить объекты в CoreData. Загрузка и декодирование JSON работает, но у меня проблемы с сохранением объектов непосредственно в CoreData.

Я пытался создать объект для моих Объектов, но Приложение не сохраняет Объекты в CoreData.

Я всегда получаю сообщение об ошибке: Неразрешенная ошибка nilError, Операция не может быть завершена. (Foundation._GenericObjCError error 0.). Не знаю, почему он больше не работает

Я использую это для загрузки и декодирования JSON:

class ItemDownloader: ObservableObject {

    @Published var items: Items = [Item]()

    @Environment(\.managedObjectContext) var managedObjectContext


    let itemEndpoint = „https:…………“

    init() {
        guard let url = URL(string: itemEndpoint) else { return }
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            do {
                guard let data = data else { return }
                let items = try JSONDecoder().decode(Items.self, from: data)
                print(items)
                DispatchQueue.main.async {
                    self.items = items

                    }

                    do {
                        guard let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] else {return}


                        let coreitems: [CoreItem] = jsonArray.compactMap { [weak self] in
                            guard
                            let name = $0["name"] as? String,
                            let id = $0["id"] as? Int16
                                else {return nil  }
                            print(name)
                            print(id)


                            let coreitem = CoreItem(context: self!.managedObjectContext)
                            coreitem.name = name
                            coreitem.id = id

                            print(coreitem.name)
                            print(coreitem.id)


                            return coreitem

                                }

                        do{
                          try self.managedObjectContext.save()
                        } catch{
                            print(error)
                        }
                        print(coreitems)
                        print(NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last!);



                    }

               } catch {
                print("Error decoding JSON: ", error)
            }
        }.resume()
    }
}

И это для хранения в CoreData:


public class CoreItem: NSManagedObject, Identifiable {
    @NSManaged public var name: String
    @NSManaged public var id: Int16

}

extension CoreItem {

    static func getAllCoreItems() -> NSFetchRequest <CoreItem> {
        let request:NSFetchRequest<CoreItem> = CoreItem.fetchRequest() as!
        NSFetchRequest<CoreItem>

        let sortDescriptor = NSSortDescriptor(key: "id", ascending: true)

        request.sortDescriptors = [sortDescriptor]

        return request
    }
}

Как сохранить объекты в CoreData?

Спасибо за помощь.

1 Ответ

0 голосов
/ 07 ноября 2019

Я рекомендую сделать CoreItem соответствующим Decodable.

Прежде всего создайте два расширения, чтобы иметь возможность передать экземпляр NSManagedObjectContext в JSONDecoder

extension CodingUserInfoKey {
    static let context = CodingUserInfoKey(rawValue: "context")!
}

extension JSONDecoder {
    convenience init(context: NSManagedObjectContext) {
        self.init()
        self.userInfo[.context] = context
    }
}

Реализуйте требуемый Decodable метод в CoreItem

public class CoreItem: NSManagedObject, Identifiable, Decodable {
    @NSManaged public var name: String
    @NSManaged public var id: Int16

    private enum CodingKeys: String, CodingKey { case name, id}

    public required convenience init(from decoder: Decoder) throws {
       guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Error: NSManagedObjectContext not available") }
       let entity = NSEntityDescription.entity(forEntityName: "CoreItem", in: context)!
       self.init(entity: entity, insertInto: context)
       let values = try decoder.container(keyedBy: CodingKeys.self)
       name = try values.decode(String.self, forKey: .name)
       id = try values.decode(Int16.self, forKey: .id)
    }
}

Код dataTask можно уменьшить до

  URLSession.shared.dataTask(with: url) { (data, response, error) in
        do {
            guard let data = data else { return }
            let decoder = JSONDecoder(context: self.managedObjectContext)
            let coreitems = try decoder.decode([CoreItem].self, from: data)
            print(coreitems)      
            try self.managedObjectContext.save()
        } catch {
          print(error)
        }
    }.resume()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...