2 votes

CoreData + Codable ne sauvegarde pas

Je suis en train d'essayer de récupérer des données et de les stocker dans CoreData. La récupération des données fonctionne bien, mais les données ne sont pas enregistrées de manière persistante.

Voici le code que j'utilise pour essayer de sauvegarder dans CoreData :

guard let codingUserInfoKeyManagedObjectContext = CodingUserInfoKey.context else {
                        fatalError("Impossible de récupérer le contexte de l'objet géré")
                    }
                    let context = CoreDataHelper.sharedInstance.persistentContainer.viewContext
                    let decoder = JSONDecoder()
                    decoder.userInfo[codingUserInfoKeyManagedObjectContext] = context
                    _ = try decoder.decode(DeltaModel.self, from: actualData) //nous obtiendrons la valeur d'un autre contexte en utilisant une requête de recherche plus tard...
                    try context.save()
                    let oilArray : [Oil] = self.fetchFromStorage()!
                    print(oilArray)

Cela affiche le contenu du tableau, mais quand on re-charge l'application, en refaisant la récupération des données, un tableau vide est renvoyé. Voici le modèle pour l'objet NSManagedObject de type Oil :

public class Oil: NSManagedObject, Codable {

enum CodingKeys: String, CodingKey {
    case resourceType = "resource_type"
    case id, name
    case imageURL = "image_url"
    case color
    case latinName = "latin_name"
    case emotions
    case safetyInformation = "safety_information"
    case fact, research
    case viewsCount = "views_count"
    case commentsCount = "comments_count"
    case blendsWith = "blends_with"
    case foundInBlends = "found_in_blends"
    case properties
    case sourcingMethods = "sourcing_methods"
    case usages
}

required convenience public init(from decoder: Decoder) throws {
    guard let context = decoder.userInfo[CodingUserInfoKey.context!] as? NSManagedObjectContext else { fatalError() }
    guard let entity = NSEntityDescription.entity(forEntityName: "Oil", in: context) else { fatalError() }

    self.init(entity: entity, insertInto: context)

    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.resourceType = try! container.decodeIfPresent(String.self, forKey: .resourceType)!
    self.id = try! container.decodeIfPresent(Int64.self, forKey: .id)!
    self.name = try! container.decodeIfPresent(String.self, forKey: .name)!
    self.imageURL = try! container.decodeIfPresent(String.self, forKey: .imageURL)!
    self.color = try! container.decodeIfPresent(String.self, forKey: .color)!
    self.viewsCount = try! container.decodeIfPresent(Int64.self, forKey: .viewsCount)!
    self.viewsCount = try! container.decodeIfPresent(Int64.self, forKey: .viewsCount)!
    self.commentsCount = try! container.decodeIfPresent(Int64.self, forKey: .commentsCount)!
    self.latinName = try! container.decodeIfPresent(String.self, forKey: .latinName)!
}

public func encode(to encoder: Encoder) throws {

}

}

Je ne vois pas de base de données SQLLite sur le simulateur ou sur un appareil réel non plus. On dirait que c'est enregistré temporairement.

Mise à jour : Contenu de la classe CoreDataHelper :

class CoreDataHelper {

static let sharedInstance: CoreDataHelper = CoreDataHelper()

func getItems(predicate : NSPredicate? = nil) -> [T]{
    do {
        let reqest = T.fetchRequest()
        reqest.predicate = predicate
        if let items = try persistentContainer.viewContext.fetch(reqest) as? [T] {
            return items
        } else {
            return [T]()
        }
    } catch let error as NSError {
        print("Impossible de récupérer. \(error), \(error.userInfo)")
        return [T]()
    }
}

func getObjectBy(id : NSManagedObjectID) -> T? {
    if let object = try? persistentContainer.viewContext.existingObject(with: id) as? T {
        return object
    }
    else {
        return nil
    }
}

var persistentContainer: NSPersistentContainer = {
    let description = NSPersistentStoreDescription()

    let container = NSPersistentContainer(name: "ELModel")

    container.persistentStoreDescriptions = [description]
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            print("Erreur non résolue \(error), \(error.userInfo)")
        }
    })
    return container
}()

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            print("Erreur non résolue \(nserror), \(nserror.userInfo)")
        }
    }
}

}

2voto

Fabian Points 1191

NSPersistentStoreDescription() crée une description vide où même l'URL du magasin n'est pas définie. Utilisez NSPersistentStoreDescription(url:) à la place.

Vous pouvez utiliser container.persistentStoreDescriptions.first!.url! pour obtenir l'URL par défaut, qui est initialisée avec NSPersistentStoreContainer(_) et donc utilisable avant le chargement.

Vous pouvez afficher l'URL actuellement utilisée avec:

print(container.persistentStoreCoordinator.persistentStores.first!.url!)

Code de création de NSPersistentContainer mis à jour

var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "ELModel")

    let storeURL = container.persistentStoreDescriptions.first!.url!
    let description = NSPersistentStoreDescription(url: storeURL)

    container.persistentStoreDescriptions = [description]
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            print("Erreur non résolue \(error), \(error.userInfo)")
        }
    })
    return container
}()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X