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
}
}