我正在尝试创建一个与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)")
}
}
}
首先保存私有队列,然后保存主队列。
答案 0 :(得分:1)
let mainContext = persistentContainer.viewContext
let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateContext.parent = mainContext
您编辑上下文,然后保存相同的上下文以保留更改。在.viewContext
上创建子上下文并保存所述子上下文不会保存.viewContext
本身(在此进行更改)。
如果要使用后台队列,请首先在.viewContext
上设置var automaticallyMergesChangesFromParent: Bool,在该位置要从后台队列接收更改。然后,您创建一个后台上下文,在其上设置来自.viewContext
的相同persistentStoreCoordinator,对其进行更改,然后保存后台队列。
使用privateContext.perform
是一个好的开始。如果您首先在创建报价的上下文中包装要引用的更改,那么效果会更好,因此您可以通过上下文使用的同一线程来访问报价。
答案 1 :(得分:1)
这是Apple 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
,但这需要更多的努力。