Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 使用CoreData的合适单例类_Swift_Core Data - Fatal编程技术网

Swift 使用CoreData的合适单例类

Swift 使用CoreData的合适单例类,swift,core-data,Swift,Core Data,我正在尝试创建一个与NSManagedObjectContext一起工作的单例类 这是一节课: import Foundation import CoreData class PersistenceService{ init(){} // MARK: - Core Data stack static var context: NSManagedObjectContext { return persistentContainer.viewContext

我正在尝试创建一个与
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,然后保存主quoue

let mainContext = persistentContainer.viewContext

let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateContext.parent = mainContext
您可以编辑一个上下文,然后保存相同的上下文以保持更改。创建
.viewContext
的子上下文并保存所述子上下文不会保存所做更改的
.viewContext
本身

如果要使用后台队列,请首先在
.viewContext
上设置要从后台队列接收更改的位置。然后创建一个后台上下文,在其上设置相同的persistentStoreCoordinator(来自
.viewContext
),对其进行更改,然后保存后台队列


使用
privateContext.perform
是一个良好的开端。如果您将对quote所做的更改包装在一个perform中,并通过创建quote的上下文执行,那么您可以通过上下文使用的相同线程访问quote。

以下是Apple示例中的单例


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

注意:您不需要创建私有队列来保存
viewContext
,您目前正在进行更改。如果您创建了一个私有队列,将其设置为“将更改流保存到viewContext”并对私有队列进行更改,则必须保存此私有队列。在不更改队列之前保存队列是毫无意义的,因为它没有任何作用。不要对CoreData使用单例,请使用依赖项注入。@trapper为什么依赖项注入更好,我不应该使用单例?
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
    }
}