虽然项目正在保存在核心数据中,但在重新启动之前无法查看它们
Although items are being saved in core data, not able to view them until a relaunch
这是一个示例,其中 FetchedResultsController
在 ViewController
中使用,并且来自另一个 ViewController
的保存没有传递给它。
MainVC.swift
lazy var coreDataManager = CoreDataManager()
// Initialize fetched request
private var fetchRecordRequestController: NSFetchedResultsController = NSFetchedResultsController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Initialize managedObjectContext
let mainManagedObjectContext = coreDataManager.managedObjectContext
// Create Fetch Request
let fetchRequest = NSFetchRequest(entityName: "Record")
// Configure Fetch Request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
// Initialize Fetched Results Controller
fetchRecordRequestController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: mainManagedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
// Configure Fetched Results Controller
fetchRecordRequestController.delegate = self
// Fetch data from object
do {
try fetchRecordRequestController.performFetch()
} catch let fetchError as NSError {
print("(RootViewController)fetchError: \(fetchError), \(fetchError.userInfo)")
}
// Add observer in NSNotificationCenter for NSManagedObjectContextObjectsDidChange
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(managedObjectContextObjectsDidChange), name: NSManagedObjectContextObjectsDidChangeNotification, object: mainManagedObjectContext)
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
// MARK: - NSFetchedResultsController Delegate Methods
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableView.beginUpdates()
}
// Delete corresponding row in tableView
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
case .Delete:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Update:
tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Move:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
func managedObjectContextObjectsDidChange(notification: NSNotification) {
let mainManagedObjectContext = coreDataManager.managedObjectContext
guard let userInfo = notification.userInfo else { return }
if let inserts = userInfo[NSInsertedObjectsKey] as? Set<NSManagedObject> where inserts.count > 0 {
print("--- INSERTS ---")
print(inserts)
print("+++++++++++++++")
do {
try mainManagedObjectContext.save()
} catch let saveError as NSError {
print("(RootViewController)saveError: \(saveError), \(saveError.userInfo)")
}
}
if let updates = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> where updates.count > 0 {
print("--- UPDATES ---")
for update in updates {
print(update.changedValues())
}
print("+++++++++++++++")
}
if let deletes = userInfo[NSDeletedObjectsKey] as? Set<NSManagedObject> where deletes.count > 0 {
print("--- DELETES ---")
print(deletes)
print("+++++++++++++++")
}
}
AddRecordVC.swift
// Method to save the extracted values to CoreData Objects
private func saveValues() {
// Initializing
let mainManagedObjectContext = coreDataManager.managedObjectContext
// Initialize entity description
let RecordDescription = NSEntityDescription.entityForName("Record",inManagedObjectContext:mainManagedObjectContext)
let record = Record(entity: RecordDescription!, insertIntoManagedObjectContext: mainManagedObjectContext)
// Set object values from temporary variables
record.date = dateTemp!
record.tareWeight = tareWeightTemp
record.grossWeight = grossWeightTemp
record.nettWeight = nettWeightTemp
record.numberOfBags = numberOfBagsTemp
record.weightOfBags = weightOfBagsTemp
record.rivaju = rivajuTemp
record.putti = puttiTemp
record.rateOfPaddy = rateOfPaddyTemp
record.amount = amountTemp
// Save the object
do {
if mainManagedObjectContext.hasChanges {
try mainManagedObjectContext.save()
}
} catch let saveError as NSError {
print("(AddRecordViewController)saveError: \(saveError), \(saveError.userInfo)")
}
}
一旦 AddRuleVC 返回到 RootVC,视图就不会刷新。 但是应用程序退出并重新启动后,它确实显示了数据。单独的class用于CoreDataStack,如下所示。
CoreDataManager.swift
class CoreDataManager: NSObject {
// MARK: - Core Data Stack
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle().URLForResource("App Name", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return managedObjectContext
}()
// 标记:- 辅助方法
func saveContext () {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
lazy var applicationDocumentsDirectory: NSURL = {
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count-1]
}()
}
您的 CoreDataManager
class 正在 AddRecordVC
中生成一个新的托管对象上下文,与 MainVC
中的不同,因此当您保存第二个上下文时,持久存储将会更新,但更改不会反映在第一个上下文中,除非您合并更改。
这样不好,主线程只需要一个上下文。所以你应该做的是对托管对象上下文使用依赖注入。当您的应用程序启动时启动 CoreDataManager
,然后将上下文注入 MainVC
,然后当您转到 AddRecordVC
时,也只需将相同的上下文也传递到那里。
您需要在保存新项目后通过异步执行 tableview.reloadData()
来重新加载您的表格视图。
这是一个示例,其中 FetchedResultsController
在 ViewController
中使用,并且来自另一个 ViewController
的保存没有传递给它。
MainVC.swift
lazy var coreDataManager = CoreDataManager() // Initialize fetched request private var fetchRecordRequestController: NSFetchedResultsController = NSFetchedResultsController() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. // Initialize managedObjectContext let mainManagedObjectContext = coreDataManager.managedObjectContext // Create Fetch Request let fetchRequest = NSFetchRequest(entityName: "Record") // Configure Fetch Request fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] // Initialize Fetched Results Controller fetchRecordRequestController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: mainManagedObjectContext, sectionNameKeyPath: nil, cacheName: nil) // Configure Fetched Results Controller fetchRecordRequestController.delegate = self // Fetch data from object do { try fetchRecordRequestController.performFetch() } catch let fetchError as NSError { print("(RootViewController)fetchError: \(fetchError), \(fetchError.userInfo)") } // Add observer in NSNotificationCenter for NSManagedObjectContextObjectsDidChange NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(managedObjectContextObjectsDidChange), name: NSManagedObjectContextObjectsDidChangeNotification, object: mainManagedObjectContext) override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self) } // MARK: - NSFetchedResultsController Delegate Methods func controllerWillChangeContent(controller: NSFetchedResultsController) { tableView.beginUpdates() } // Delete corresponding row in tableView func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { switch type { case .Insert: tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) case .Delete: tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) case .Update: tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) case .Move: tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) } } func controllerDidChangeContent(controller: NSFetchedResultsController) { tableView.endUpdates() } func managedObjectContextObjectsDidChange(notification: NSNotification) { let mainManagedObjectContext = coreDataManager.managedObjectContext guard let userInfo = notification.userInfo else { return } if let inserts = userInfo[NSInsertedObjectsKey] as? Set<NSManagedObject> where inserts.count > 0 { print("--- INSERTS ---") print(inserts) print("+++++++++++++++") do { try mainManagedObjectContext.save() } catch let saveError as NSError { print("(RootViewController)saveError: \(saveError), \(saveError.userInfo)") } } if let updates = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> where updates.count > 0 { print("--- UPDATES ---") for update in updates { print(update.changedValues()) } print("+++++++++++++++") } if let deletes = userInfo[NSDeletedObjectsKey] as? Set<NSManagedObject> where deletes.count > 0 { print("--- DELETES ---") print(deletes) print("+++++++++++++++") } }
AddRecordVC.swift
// Method to save the extracted values to CoreData Objects private func saveValues() { // Initializing let mainManagedObjectContext = coreDataManager.managedObjectContext // Initialize entity description let RecordDescription = NSEntityDescription.entityForName("Record",inManagedObjectContext:mainManagedObjectContext) let record = Record(entity: RecordDescription!, insertIntoManagedObjectContext: mainManagedObjectContext) // Set object values from temporary variables record.date = dateTemp! record.tareWeight = tareWeightTemp record.grossWeight = grossWeightTemp record.nettWeight = nettWeightTemp record.numberOfBags = numberOfBagsTemp record.weightOfBags = weightOfBagsTemp record.rivaju = rivajuTemp record.putti = puttiTemp record.rateOfPaddy = rateOfPaddyTemp record.amount = amountTemp // Save the object do { if mainManagedObjectContext.hasChanges { try mainManagedObjectContext.save() } } catch let saveError as NSError { print("(AddRecordViewController)saveError: \(saveError), \(saveError.userInfo)") } }
一旦 AddRuleVC 返回到 RootVC,视图就不会刷新。 但是应用程序退出并重新启动后,它确实显示了数据。单独的class用于CoreDataStack,如下所示。
CoreDataManager.swift
class CoreDataManager: NSObject { // MARK: - Core Data Stack lazy var managedObjectModel: NSManagedObjectModel = { let modelURL = NSBundle.mainBundle().URLForResource("App Name", withExtension: "momd")! return NSManagedObjectModel(contentsOfURL: modelURL)! }() lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { // Create the coordinator and store let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite") var failureReason = "There was an error creating or loading the application's saved data." do { try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil) } catch { // Report any error we got. var dict = [String: AnyObject]() dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" dict[NSLocalizedFailureReasonErrorKey] = failureReason dict[NSUnderlyingErrorKey] = error as NSError let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") abort() } return coordinator }() lazy var managedObjectContext: NSManagedObjectContext = { let coordinator = self.persistentStoreCoordinator var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) managedObjectContext.persistentStoreCoordinator = coordinator managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy return managedObjectContext }()
// 标记:- 辅助方法
func saveContext () { if managedObjectContext.hasChanges { do { try managedObjectContext.save() } catch { let nserror = error as NSError NSLog("Unresolved error \(nserror), \(nserror.userInfo)") abort() } } } lazy var applicationDocumentsDirectory: NSURL = { let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) return urls[urls.count-1] }() }
您的 CoreDataManager
class 正在 AddRecordVC
中生成一个新的托管对象上下文,与 MainVC
中的不同,因此当您保存第二个上下文时,持久存储将会更新,但更改不会反映在第一个上下文中,除非您合并更改。
这样不好,主线程只需要一个上下文。所以你应该做的是对托管对象上下文使用依赖注入。当您的应用程序启动时启动 CoreDataManager
,然后将上下文注入 MainVC
,然后当您转到 AddRecordVC
时,也只需将相同的上下文也传递到那里。
您需要在保存新项目后通过异步执行 tableview.reloadData()
来重新加载您的表格视图。