CoreData + Codable не сохраняется - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь снять некоторые данные и сохранить их в CoreData. Выгрузка данных работает нормально, но данные не сохраняются постоянно.

Вот код, который я использую для сохранения CoreData:

guard let codingUserInfoKeyManagedObjectContext = CodingUserInfoKey.context else {
                        fatalError("Failed to retrieve managed object context")
                    }
                    let context = CoreDataHelper.sharedInstance.persistentContainer.viewContext
                    let decoder = JSONDecoder()
                    decoder.userInfo[codingUserInfoKeyManagedObjectContext] = context
                    _ = try decoder.decode(DeltaModel.self, from: actualData) //we'll get the value from another context using a fetch request later...
                    try context.save()
                    let oilArray : [Oil] = self.fetchFromStorage()!
                    print(oilArray)

Это печатает содержимое массива, но при повторной выборке при перезагрузке приложения возвращает пустой массив. Вот модель для масла NSManagedObject:

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 {

}

}

Невозможно увидеть SQLLite DB ни на симуляторе, ни на реальном устройстве. Это как временная экономия.

Обновление: содержимое класса CoreDataHelper:

class CoreDataHelper {

static let sharedInstance: CoreDataHelper = CoreDataHelper()

func getItems<T : NSManagedObject>(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("Could not fetch. \(error), \(error.userInfo)")
        return [T]()
    }
}

func getObjectBy<T : NSManagedObject>(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("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
            print("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}

}

1 Ответ

0 голосов
/ 29 августа 2018

NSPersistentStoreDescription() создает пустое описание, в котором даже не указан URL магазина. Вместо этого используйте NSPersistentStoreDescription(url:).

Вы можете использовать container.persistentStoreDescriptions.first!.url! для получения URL-адреса по умолчанию, который инициализируется с помощью NSPersistentStoreContainer(_) и может использоваться перед загрузкой.

Вы можете отобразить текущий используемый URL с помощью:

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

Обновлен код создания NSPersistentContainer

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("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()
...