代码之家  ›  专栏  ›  技术社区  ›  Maysam

使用CoreData的合适的singleton类

  •  0
  • Maysam  · 技术社区  · 6 年前

    我试图创建一个与 NSManagedObjectContext .

    这是班级:

    import Foundation
    import CoreData
    
    class PersistenceService{
        init(){}
        // MARK: - Core Data stack
        static var context: NSManagedObjectContext {
            return persistentContainer.viewContext
        }
    
        static var persistentContainer: NSPersistentContainer = {
    
            let container = NSPersistentContainer(name: "frazeit")
            container.loadPersistentStores(completionHandler: { (storeDescription, error) in
                if let error = error as NSError? {
    
                    fatalError("Unresolved error \(error), \(error.userInfo)")
                }
            })
            return container
        }()
    
        // MARK: - Core Data Saving support
        static func saveContext () {
            let mainContext = persistentContainer.viewContext
    
            let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
            privateContext.parent = mainContext
    
            privateContext.perform {
                if privateContext.hasChanges {
                    do {
                        try privateContext.save()
                    } catch {
                        let nserror = error as NSError
                        fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                    }
    
                }
            }
    
        }
    
    }
    

    在某些情况下,当应用程序打开时,它不会将更改推送到持久存储中,而持久容器会更改,但当我重新运行时,应用程序更改将消失。什么是将更改保存到持久性存储中的正确方法。

    这个类不能正常工作:

    class func add(word: String, quotes:[Quotes], language: String){
        for item in quotes {
            if let phrase = item.phrase, let author = item.author {
                let quote = CachedQuotes(context: PersistenceService.context)
                quote.phrase = phrase
                quote.date = Date() as NSDate
                quote.keyword = word
                quote.language = language
                quote.author = author
                PersistenceService.saveContext()
            }
    
        }
    }
    

    我调用它来保存从网络中获取的报价:

    override func viewDidLoad() {
        let quotes =  CachedQuotes.getAllQuotes()
        //Prints the number of saved records which is 0 now
        self.getQuote { (result, error) in
            if let qoutes = result?.quotes {
                CachedQuotes.add(word: "friend", quotes: qoutes, language: "en")
            }
        }
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let quotes =  CachedQuotes.getAllQuotes()
        //Prints the number of saved records which is 10 now
    }
    

    但当我重新运行应用程序时,没有任何内容保存到持久性容器中。

    更新: 下面的代码现在可以工作了

    static func saveContext () {
            let mainContext = persistentContainer.viewContext
            let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
            privateContext.automaticallyMergesChangesFromParent = true
            privateContext.parent = mainContext
            privateContext.perform {
                do {
                    try privateContext.save()
                    mainContext.perform({
                        do {
                            try mainContext.save()
                        } catch {
                            let nserror = error as NSError
                            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                        }
                    })
                } catch {
                    let nserror = error as NSError
                    fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                }
            }
        }
    

    首先它保存了私人的quoue然后保存了主要的。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Fabian    6 年前
    let mainContext = persistentContainer.viewContext
    
    let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    privateContext.parent = mainContext
    

    您可以编辑一个上下文,然后保存相同的上下文以保持更改。创建子上下文以 .viewContext 保存所述子上下文并不能保存 .viewContext 本身,就是你做出改变的地方。

    如果要使用后台队列,请首先设置 var automaticallyMergesChangesFromParent: Bool .viewContext 从后台队列接收更改的位置。然后创建一个背景上下文,在其上设置相同的persistentstorecordinator .viewContext ,对其进行更改,然后保存后台队列。

    使用 privateContext.perform 是个好的开始。如果您将对quote的更改包装在perform中,并首先在其中创建quote的上下文中执行,那么您可以做得更好,这样您就可以通过上下文使用的同一线程访问quote。

        2
  •  1
  •   malhal Benzy Neez    5 年前

    这是苹果的单曲 Refreshing and Maintaining Your App Using Background Tasks 样品。

    import Foundation
    import CoreData
    
    class PersistentContainer: NSPersistentContainer {
        private static let lastCleanedKey = "lastCleaned"
    
        static let shared: PersistentContainer = {
            ValueTransformer.setValueTransformer(ColorTransformer(), forName: NSValueTransformerName(rawValue: String(describing: ColorTransformer.self)))
    
            let container = PersistentContainer(name: "ColorFeed")
            container.loadPersistentStores { (desc, error) in
                if let error = error {
                    fatalError("Unresolved error \(error)")
                }
    
                print("Successfully loaded persistent store at: \(desc.url?.description ?? "nil")")
            }
    
            container.viewContext.automaticallyMergesChangesFromParent = true
            container.viewContext.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyStoreTrumpMergePolicyType)
    
            return container
        }()
    
        var lastCleaned: Date? {
            get {
                return UserDefaults.standard.object(forKey: PersistentContainer.lastCleanedKey) as? Date
            }
            set {
                UserDefaults.standard.set(newValue, forKey: PersistentContainer.lastCleanedKey)
            }
        }
    
        override func newBackgroundContext() -> NSManagedObjectContext {
            let backgroundContext = super.newBackgroundContext()
            backgroundContext.automaticallyMergesChangesFromParent = true
            backgroundContext.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyStoreTrumpMergePolicyType)
            return backgroundContext
        }
    }
    

    就我个人而言,我更喜欢通过 NSPersistentContainer 通过依赖注入,但需要更多的努力。