Операции с базовыми данными в нескольких потоках, вызывающие вставку, но не выбирающие - PullRequest
0 голосов
/ 10 июня 2019

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

Проблема в том, что я могу вставить данные в CoreData, но при получении из CoreData результаты равны нулю, это происходит, когда я убиваю свое приложение и извлекаю данные из базы данных . Это как-то связано с NSMangedObjectContext, но я не могу понять.

Вот мой фрагмент кода:

class CoreDataManager {

    static let sharedManager = CoreDataManager()
    private init() {}

    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "My_Contacts")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    func saveContext() {
        let context = CoreDataManager.sharedManager.persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

    func insertContact(id:Int, firstName : String,lastName : String,emaild : String,isFavorite : Bool,phoneNum : String,profilePic : String,sync : Bool) -> Contact? {
        let managedContext = CoreDataManager.sharedManager.persistentContainer.viewContext
        let privateManagedObjectContext: NSManagedObjectContext = {
            //NSPrivateQueueConcurrencyType
            let moc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
            moc.parent = managedContext
            return moc
        }()


        let entity = NSEntityDescription.entity(forEntityName: "Contact",
                                                in: privateManagedObjectContext)!
        let contact = NSManagedObject(entity: entity,
                                     insertInto: privateManagedObjectContext)
        contact.setValue(firstName, forKey: "first_name")
        contact.setValue(lastName, forKey: "last_name")
        contact.setValue(emaild, forKey: "email")
        contact.setValue(isFavorite, forKey: "favorite")
        contact.setValue(phoneNum, forKey: "phone_number")
        contact.setValue(profilePic, forKey: "profile_pic")
        contact.setValue(sync, forKey: "syncStatus")
        contact.setValue(id, forKey: "contactId")

        do {
            try privateManagedObjectContext.save()
            return contact as? Contact
        } catch let error as NSError {
            print("Could not save. \(error), \(error.userInfo)")
            return nil
        }
    }


    func fetchAllContacts() -> [Contact]?{

        let managedContext = CoreDataManager.sharedManager.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Contact")

        do {
            let people = try managedContext.fetch(fetchRequest)
            return people as? [Contact]
        } catch let error as NSError {
            print("Could not fetch. \(error), \(error.userInfo)")
            return nil
        }
    }
}

Ответы [ 2 ]

1 голос
/ 10 июня 2019

, поэтому я использую основные данные в нескольких потоках, чтобы быть потокобезопасными

Что вы подразумеваете под этим?Использование нескольких потоков не делает ничего поточно-ориентированным.Безопасность потоков связана с тем, что вы можете без проблем запускать свой код в нескольких потоках, и обычно требуется, чтобы вы приняли ряд мер предосторожности, чтобы потоки не мешали друг другу.

Проблема в том, что яЯ могу вставить данные в CoreData, но при получении из CoreData результаты равны нулю, это происходит, когда я убиваю свое приложение и получаю данные из базы данных.Это как-то связано с NSMangedObjectContext, но я не могу понять это.

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

Несколько причин, по которым вы можете не видеть добавляемые вами объекты:

  • Вы добавляете объекты и пытаетесь прочитать их обратно в разных контекстах.

  • Вы никогда не сохраняете контекст после добавления объектов.

  • Вы сохраняете контекст, в котором вы добавили объект, но родительский контекст (контексты управляемого объекта являются иерархическими) никогда не сохраняется.

  • Вы пытаетесьсохранить контекст после добавления объектов, но сохранение не удается.

  • Вы используете один и тот же контекст в нескольких потоках, не заботясь о сериализации операций над контекстом (то есть, ваш код не поточно-ориентированный).

Что вы действительно должны сделать, чтобы понять это, так это вернуть себя в состояние, в котором вы можете хранитьи получать объекты надежно.Попробуйте использовать только один поток и убедитесь, что ваши операции работают.Если они этого не делают, сначала исправьте это.Затем получите полное представление о том, как работают контексты управляемого объекта и как их использовать.Наконец, прочитайте о параллелизме и основных данных .

1 голос
/ 10 июня 2019

Поскольку вы используете несколько MOC (контекст управляемого объекта), вам необходимо сохранить оба контекста

Вы установили родитель privateManagedObjectContext на managedContext, но не сохраняете managedContext

После звонка privateManagedObjectContext.save() вам также необходимо позвонить managedContext.save()

...