NSFetchedResultsController can't update the tableView swift4 - core-data

I'm trying to make it work for last couple of days and can't get it working. Its something tiny detail obviously I can't seem to find.
Could you take a look and give me some insights about my code?
I'm trying to update the logView with app savings in the coredata.
Here's the entire code for ViewController and CoreData Handler.
/// fetch controller
lazy var fetchController: NSFetchedResultsController = { () -> NSFetchedResultsController<NSFetchRequestResult> in
let entity = NSEntityDescription.entity(forEntityName: "Logs", in: CoreDataHandler.sharedInstance.backgroundManagedObjectContext)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
fetchRequest.entity = entity
let nameDescriptor = NSSortDescriptor(key: "name", ascending: false)
fetchRequest.sortDescriptors = [nameDescriptor]
let fetchedController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: CoreDataHandler.sharedInstance.backgroundManagedObjectContext, sectionNameKeyPath: "duration", cacheName: nil)
fetchedController.delegate = self as? NSFetchedResultsControllerDelegate
return fetchedController
}()
override func viewDidLoad() {
title = "Week Log"
tableView.tableFooterView = UIView(frame: CGRect.zero)
tableView.separatorColor = UIColor.black
tableView.backgroundColor = UIColor.red
refreshView()
loadNormalState()
loadCoreDataEntities()
}
/**
Refresh the view, reload the tableView.
*/
func refreshView() {
loadCoreDataEntities()
tableView.reloadData()
}
/**
Load history entities from core data. (I'm printing on the console and
be able to see the the fetched data but I can't load it to tableView.)
*/
func loadCoreDataEntities() {
do {
try fetchController.performFetch()
} catch {
print("Error occurred while fetching")
}
}
import Foundation
import CoreData
class CoreDataHandler: NSObject {
/**
Creates a singleton object to be used across the whole app easier
- returns: CoreDataHandler
*/
class var sharedInstance: CoreDataHandler {
struct Static {
static var instance: CoreDataHandler = CoreDataHandler()
}
return Static.instance
}
lazy var backgroundManagedObjectContext: NSManagedObjectContext = {
let backgroundManagedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
let coordinator = self.persistentStoreCoordinator
backgroundManagedObjectContext.persistentStoreCoordinator = coordinator
return backgroundManagedObjectContext
}()
lazy var objectModel: NSManagedObjectModel = {
let modelPath = Bundle.main.url(forResource: "Model", withExtension: "momd")
let objectModel = NSManagedObjectModel(contentsOf: modelPath!)
return objectModel!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.objectModel)
// Get the paths to the SQLite file
let storeURL = self.applicationDocumentsDirectory().appendingPathComponent("Model.sqlite")
// Define the Core Data version migration options
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
// Attempt to load the persistent store
var error: NSError?
var failureReason = "There was an error creating or loading the application's saved data."
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: options)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject
dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return persistentStoreCoordinator
}()
func applicationDocumentsDirectory() -> NSURL {
return FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).last! as NSURL
}
func saveContext() {
do {
try backgroundManagedObjectContext.save()
} catch {
print("Error while saving the object context")
// Error occured while deleting objects
}
}

You have a data source delegate somewhere. That data source delegate tells the table view how many items there are, and what their contents is. How does it know how many items? That must be stored somewhere.
When the fetch controller is successful, it must modify the data that the data source delegate relies on in some way, and then call reloadData. Are you doing this? Are you doing anything that causes the data source delegate to change the number of items it reports?
And calling loadCoreDataEntities, immediately followed by reloadData, is nonsense. loadCoreDataEntities is asynchronous. By the time you call reloadData, it hasn't loaded any entities yet. realodData is called when loadCoreDataEntities has finished.

Related

How do I get SwiftUI to work with Core Data (after starting a project)?

I get this error when trying to get Xcode working with Core Data. Any help would be very appreciated.
Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x6000008a8820>
After commenting out all the other environments so that the persistence envinronment is only used in the top level, I still have the same error.
Here is the Apps Top-Level Swift File:
import SwiftUI
import CoreData
#main
struct Draw_DailyApp: App {
let persistenceController = PersistenceController.shared
#Environment(\.scenePhase) var scenePhase
#FetchRequest(entity: Drawing.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Drawing.img, ascending: true)])
var orders: FetchedResults<Drawing>
#State var showOrderSheet = false
// Creating a global environment and placing it into the environment
#ObservedObject var searchObjectController: SearchObjectController = SearchObjectController()
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(self.searchObjectController)
}
.onChange(of: scenePhase) { _ in
persistenceController.save()
}
}
}
and here is the file where persistent controller is used (Core Data xcdatamodeld has one Binary Data attribute called img)
Persistence.Swift
import CoreData
import UIKit
struct PersistenceController {
static let shared = PersistenceController()
func save() {
let context = container.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Show some error here
}
}
}
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for _ in 0..<10 {
let newItem = Drawing(context: viewContext)
newItem.img = Data()
newItem.date = "02081999"
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "DrawDaily")
if inMemory {
container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
PS: I didn't start this project with Core Data, I added it in later
Your #FetchRequest doesn't have a NSManagedObjectContext upon init. You are creating it with this line
let persistenceController = PersistenceController.shared
Your #FetchRequest has to move down into the ContentView for it to work.
This line has to be called
.environment(\.managedObjectContext, persistenceController.container.viewContext)
when initializing the View that contains the #FetchRequest

Testing Core Data

I want to set up a mock for my Core data manager.
I'm doing this the old way for the core data stack, but want to do it for the exercise.
In the main Core Data Manager I set up with
var objectContext: NSManagedObjectContext! = nil
var entity: NSEntityDescription! = nil
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
objectContext = appDelegate.persistentContainer.viewContext
entity = NSEntityDescription.entity(forEntityName: Constants.entityName, in: objectContext)!
Now obviously I can't use UIApplication's persistent container in my mock.
So I tried to use the following:
objectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
let entityOne = NSEntityDescription.insertNewObject(forEntityName: Constants.entityName, into: objectContext)
However I get the error "NSInvalidArgumentException", "+entityForName: nil is not a legal NSPersistentStoreCoordinator for searching for entity name 'TaskEntity'"
So how can I set a new objectContext for my mock?
One solution is to create a full Core Data stack but let the persistent store reside in memory only. This way you don't have to deal with some app delegate dependency. Set context to nil and remove the store from the coordinator afterwards in tearDown()
class TestExample: XCTestCase {
var storeCordinator: NSPersistentStoreCoordinator!
var managedObjectContext: NSManagedObjectContext!
var managedObjectModel: NSManagedObjectModel!
var store: NSPersistentStore!
override func setUp() {
super.setUp()
managedObjectModel = NSManagedObjectModel.mergedModel(from: nil)
storeCordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
do {
store = try storeCordinator.addPersistentStore(
ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: nil)
} catch {
XCTFail("Failed to create a persistent store, \(error)")
}
managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = storeCordinator
}

Coredata returns duplicate values. Can anyone had the same issue?

Im using swift3. When fetching data from coredata, it returns duplicate values. Using software Datum, i understood that database only contains the original value.
class DatabaseManager: NSObject {
fileprivate static let sharedManager: DatabaseManager = DatabaseManager()
class var shared: DatabaseManager {
return sharedManager
}
/*Returns the ManagedObjectContext*/
var managedObjectContext: NSManagedObjectContext!
var privateManagedObjectContext: NSManagedObjectContext!
fileprivate var completionHandler: ((_ completed: Bool)-> Void)? = nil
override init() {
privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
if let appdelegate = UIApplication.shared.delegate as? AppDelegate {
managedObjectContext = appdelegate.managedObjectContext
privateManagedObjectContext.persistentStoreCoordinator = managedObjectContext.persistentStoreCoordinator
}
}
deinit {
managedObjectContext = nil
privateManagedObjectContext = nil
}
}
//Fetching data
func getItem()->[ListItem]{
var objects = [ListItem]()
var uniqueObjects:[ListItem] = [ListItem]()
let sort = NSSortDescriptor(key: "itemName", ascending: false)
let request : NSFetchRequest<ShoppyListItem> = ShoppyListItem.fetchRequest() as NSFetchRequest<ShoppyListItem>
//let predicate = NSPredicate(format:"excludedIDContain = %#","New")
// request.predicate = predicate
request.sortDescriptors = [sort]
do {
if objects.count > 0 {
objects.removeAll()
}
objects = try managedObjectContext?.fetch(request) ?? []
return objects
} catch {
print("Error with request: \(error)")
}
return objects
}
// objects = try managedObjectContext?.fetch(request) ?? [] returns duplicated objects
i got it. Im not mistaken about the count. It was due to concurrency. i was not running fetch on the safe thread of coredata. All i had to do was put the code inside perform block.
managedObjectContext.perform(block).
Got this from stanford ios tutorial named coredata demo. Video time 26:00. The professor explains this.

Swift 3 preload from SQL files in appDelegate

I am attempting a swift 3 conversion. I was preloading data from sql files in my swift 2 project. I am unsure how to make this work in swift 3.0? Below is my swift 2 appDelegate file. In swift 3 the core data stack has changed enough, that I do not know where to try to reuse the same code that worked for me with swift 2. The code i was using that worked is listed under the comment "added for SQLite preload". Thank you
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: URL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "self.edu.SomeJunk" in the application's documents Application Support directory.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1]
}()
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = Bundle.main.url(forResource: "ESLdata", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("ESLdata.sqlite")
//ADDED FOR SQLITE PRELOAD
// Load the existing database
if !FileManager.default.fileExists(atPath: url.path) {
let sourceSqliteURLs = [Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite")!,Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-wal")!, Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-shm")!]
let destSqliteURLs = [self.applicationDocumentsDirectory.appendingPathComponent("ESLdata.sqlite"), self.applicationDocumentsDirectory.appendingPathComponent("ESLdata.sqlite-wal"), self.applicationDocumentsDirectory.appendingPathComponent("ESLdata.sqlite-shm")]
for index in 0 ..< sourceSqliteURLs.count {
do {
try FileManager.default.copyItem(at: sourceSqliteURLs[index], to: destSqliteURLs[index])
} catch {
print(error)
}
}
}
// END OF ADDED CODE
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: [NSMigratePersistentStoresAutomaticallyOption:true, NSInferMappingModelAutomaticallyOption:true])
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
print("SAVED")
} catch {
print("Save Failed")
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
The following is what I attempted to update the code to, and had no luck:
func getDocumentsDirectory()-> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "ESLdata")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
//ADDED FOR SQLITE PRELOAD
let url = self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite")
// Load the existing database
if !FileManager.default.fileExists(atPath: url.path) {
let sourceSqliteURLs = [Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite")!,Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-wal")!, Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-shm")!]
let destSqliteURLs = [self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite"), self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite-wal"), self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite-shm")]
for index in 0 ..< sourceSqliteURLs.count {
do {
try FileManager.default.copyItem(at: sourceSqliteURLs[index], to: destSqliteURLs[index])
} catch {
print(error)
}
}
}
// END OF ADDED CODE
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
This seems to be the solution I was looking for. As far as I can tell so far, it works. And sticks the the new slimmer format core data stack for iOS10.
func getDocumentsDirectory()-> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "ESLdata")
let appName: String = "ESLdata"
var persistentStoreDescriptions: NSPersistentStoreDescription
let storeUrl = self.getDocumentsDirectory().appendingPathComponent("ESLData.sqlite")
if !FileManager.default.fileExists(atPath: (storeUrl.path)) {
let seededDataUrl = Bundle.main.url(forResource: appName, withExtension: "sqlite")
try! FileManager.default.copyItem(at: seededDataUrl!, to: storeUrl)
}
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
description.url = storeUrl
container.persistentStoreDescriptions = [description]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
First of all-- the changes you have made are only partly about Swift 3. You are not required to use NSPersistentContainer, and doing so is a completely different issue from using Swift 3. You can still use all the same Core Data classes and methods as in Swift 2, but with different syntax. If you understand your older code, you're probably better off keeping the same logic and classes but with newer syntax.
If you do switch to NSPersistentContainer, the loadPersistentStores method is more or less comparable to the addPersistentStore call in your older code. When you call that method, the persistent store file is loaded, so it must exist if you want to use its data. In your older code you copy your pre-loaded data before loading the persistent store, but in your newer code you're doing it afterward. That's why you're not seeing the data.
Since you appear to be using the same default store file name that NSPersistentContainer will assume, that's probably enough. If it still doesn't find the data, you may need to create an NSPersistentStoreDescription to tell your container where to put the store file.
But if I were you I'd stick with the older approach and the newer Swift 3 syntax.

Swift SIGBART threat CoreData

I have the problem about SIGBART. i did google it and try to solve it.
but i only have it on one of my buttons.
This is how my tool bar said.
CoreData: error: -addPersistentStoreWithType:SQLite
configuration:(null)
URL:file:///var/mobile/Containers/Data/Application/D223A294-3617-494F-8774-9CA6DCB61C2D/Documents/SingleViewCoreData.sqlite
options:(null) ... returned error Error Domain=NSCocoaErrorDomain
Code=134100 "The managed object model version used to open the
persistent store is incompatible with the one that was used to create
the persistent store." UserInfo={metadata={
NSPersistenceFrameworkVersion = 637;
NSStoreModelVersionHashes = {
Item = ;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = SQLite;
NSStoreUUID = "7711BB5D-CAF4-4F2E-9122-AF54B74D3850";
"_NSAutoVacuumLevel" = 2; }, reason=The model used to open the store is incompatible with the one used to create the store} with
userInfo dictionary {
metadata = {
NSPersistenceFrameworkVersion = 637;
NSStoreModelVersionHashes = {
Item = ;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = SQLite;
NSStoreUUID = "7711BB5D-CAF4-4F2E-9122-AF54B74D3850";
"_NSAutoVacuumLevel" = 2;
};
reason = "The model used to open the store is incompatible with the one used to create the store"; } 2016-01-07 12:18:39.271
test7[2483:1077844] Unresolved error Error Domain=YOUR_ERROR_DOMAIN
Code=9999 "Failed to initialize the application's saved data"
UserInfo={NSLocalizedDescription=Failed to initialize the
application's saved data, NSLocalizedFailureReason=There was an error
creating or loading the application's saved data.,
NSUnderlyingError=0x134e63a80 {Error Domain=NSCocoaErrorDomain
Code=134100 "The managed object model version used to open the
persistent store is incompatible with the one that was used to create
the persistent store." UserInfo={metadata={
NSPersistenceFrameworkVersion = 637;
NSStoreModelVersionHashes = {
Item = ;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = SQLite;
NSStoreUUID = "7711BB5D-CAF4-4F2E-9122-AF54B74D3850";
"_NSAutoVacuumLevel" = 2; }, reason=The model used to open the store is incompatible with the one used to create the store}}},
[NSLocalizedDescription: Failed to initialize the application's saved
data, NSLocalizedFailureReason: There was an error creating or loading
the application's saved data., NSUnderlyingError: Error
Domain=NSCocoaErrorDomain Code=134100 "The managed object model
version used to open the persistent store is incompatible with the one
that was used to create the persistent store." UserInfo={metadata={
NSPersistenceFrameworkVersion = 637;
NSStoreModelVersionHashes = {
Item = ;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = SQLite;
NSStoreUUID = "7711BB5D-CAF4-4F2E-9122-AF54B74D3850";
"_NSAutoVacuumLevel" = 2; }, reason=The model used to open the store is incompatible with the one used to create the store}] (lldb)
Code on board:
import UIKit
import CoreData
class RecordTVC: UITableViewController, NSFetchedResultsControllerDelegate {
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var frc : NSFetchedResultsController = NSFetchedResultsController()
func fetchRequest() ->NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "users")
let sortDescriptior = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptior]
return fetchRequest
}
func getFRC() ->NSFetchedResultsController {
frc = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
override func viewDidLoad() {
super.viewDidLoad()
frc = getFRC()
frc.delegate = self
do {
try frc.performFetch()
} catch {
print("failed to perform fetch")
return
}
self.tableView.rowHeight = 100
}
override func viewDidAppear(animated: Bool) {
frc = getFRC()
frc.delegate = self
do {
try frc.performFetch()
} catch {
print("failed to appear")
return
}
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
_ = frc.sections?.count
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
_ = frc.sections?[section].numberOfObjects
return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
cell.textLabel?.textColor = UIColor.blueColor()
let users = frc.objectAtIndexPath(indexPath) as! Users
cell.textLabel?.text = users.name
let date = users.data
let note = users.note
cell.detailTextLabel!.text = " Date: \(date!) Note: \(note!)"
return cell
}
}
And on the appDelegate:
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
self.saveContext()
}
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "mis-dentmate.com.tw.test7" in the application's documents Application Support directory.
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count-1]
}()
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = NSBundle.mainBundle().URLForResource("test7", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// 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)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}

Resources