I am making a sprite kit game and need to save three integers: currentLevel, maxLevelReached and highScore. I would also like to implement those to iCloud, but thats another step for me, first I want to figure out the problems I have right now. Basically, I am trying to use core data to store those. In my app delegate I added the following (basically I created new project and copied core data code)
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL = {
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count-1] as! NSURL
}()
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle().URLForResource("GameState", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("APPNAME.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
coordinator = nil
// 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
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext? = {
let coordinator = self.persistentStoreCoordinator
if coordinator == nil {
return nil
}
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if let moc = self.managedObjectContext {
var error: NSError? = nil
if moc.hasChanges && !moc.save(&error) {
// 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.
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()
}
}
}
when I did that, I created my data model (File->new->CoreData->Data model) and named it GameState. I then created the entity called CurrentLevel and added attribute of type Int16 and name currentLevel. I made the entity of class Appname.CurrentLevel. Then, in my game scene I added the following properties:
var currentLevel = [NSManagedObject]()
var levelToShow: Int16!
And created these two functions to handle core data stuff.
//Handling the fetching from the CoreData
func fetchTheStuff() {
//1
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let fetchRequest = NSFetchRequest(entityName:"CurrentLevel")
//3
var error: NSError?
let fetchedResults =
managedContext.executeFetchRequest(fetchRequest,
error: &error) as? [NSManagedObject]
if let results = fetchedResults {
currentLevel = results
println(currentLevel)
} else {
println("Could not fetch \(error), \(error!.userInfo)")
}
}
//Handling the saving
func saveCurrentLevel(cLevel: Int16){
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("CurrentLevel",
inManagedObjectContext:
managedContext)
let curLevel = NSManagedObject(entity: entity!,
insertIntoManagedObjectContext:managedContext)
curLevel.setValue(name, forKey: "currentLevel")
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)")
}
}
As you can see the fetch function is still in testing stage (I am simply printing the results). If I fetch it the first time I use the app, it gives me an empty string, as it should be. However, If I try to save a number using save function and then fetch the stuff, the log screen gives me the following warning:
CoreData: warning: Unable to load class named 'appname.CurrentLevel' for entity 'CurrentLevel'. Class not found, using default NSManagedObject instead.
Knowing the function I want to achieve, seeing the method I (try) to use, does anyone know how to solve my problem?
P.S. Also, it seems that this whole core data stuff is quite complicated, I have a hard time grasping how exactly it works even though I read a quite a lot about it. So if anyone has a suggestion on decreasing the complexity to achieve the same result (hence, not using any of the functionality) , tips are more than welcome.
Answer to the initial question
Please make sure, to generate the correct classes for your Coredata Model, highlighting your entities and then chosing Editor -> Create NSObject subclass
Related
I have tableview which display list of animals.Tapping on each cell (or animal) it navigates to detail of animal and it has save button.
Whenever I save the information using core data, all the records in the core data gets over-write with last updated data.
I'm not sure what could be the reason. Reference for the code is taken form this post:
Swift 3 IOS 9 And IOS 10 Core Data
Below is the code
class CoreDataStack {
static var applicationDocumentsDirectory: URL = {
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1]
}()
static 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(for: CoreDataStack.self).url(forResource: "DatabaseTest", withExtension: "momd")! // type your database name here..
return NSManagedObjectModel(contentsOf: modelURL)!
}()
static 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: managedObjectModel)
let url = applicationDocumentsDirectory.appendingPathComponent("DatabaseTest.sqlite") // type your database name here...
var failureReason = "There was an error creating or loading the application's saved data."
let options = [NSMigratePersistentStoresAutomaticallyOption: NSNumber(value: true as Bool), NSInferMappingModelAutomaticallyOption: NSNumber(value: true as Bool)]
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, 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 coordinator
}()
static 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 = persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
static func getEntity<T: NSManagedObject>() -> T {
if #available(iOS 10, *) {
let obj = T(context: CoreDataStack.context)
return obj
} else {
guard let entityDescription = NSEntityDescription.entity(forEntityName: NSStringFromClass(T.self), in: CoreDataStack.context) else {
fatalError("Core Data entity name doesn't match.")
}
let obj = T(entity: entityDescription, insertInto: CoreDataStack.context)
return obj
}
}
// MARK: - Core Data Saving support
static 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()
}
}
}
}
On tapping save button, I call this code
let animalObj: animalTable = CoreDataStack.getEntity()
animalObj.Name = animalModel.Name
animalObj.Type = animalModel.Type
CoreDataStack.saveContext()
Not sure, where is the problem that it over-write all data in core data with last data saved.
I am getting this wrapping error when I implement my fetched managed object core data code. Currently getting fatal error: unexpectedly found nil while unwrapping an Optional value. What am I doing wrong?
ViewController:
func saveRun() {
// 1
let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext!) as! Run
savedRun.distance = NSNumber(value: distance)
savedRun.duration = (NSNumber(value: seconds))
savedRun.timestamp = NSDate() as Date
// 2
var savedLocations = [Location]()
for location in locations {
let savedLocation = NSEntityDescription.insertNewObject(forEntityName: "Location",
into: managedObjectContext!) as! Location
savedLocation.timestamp = (location.timestamp as NSDate) as Date
savedLocation.latitude = NSNumber(value: location.coordinate.latitude)
savedLocation.longitude = NSNumber(value: location.coordinate.longitude)
savedLocations.append(savedLocation)
}
savedRun.locations = NSOrderedSet(array: savedLocations)
run = savedRun
do{
try managedObjectContext!.save()
}catch{
print("Could not save the run!")
}
}
App Delegate:
// 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 "com.zedenem.MarathonRun" in the application's documents Application Support directory.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls.last!
}()
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: "MarathonRun", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
// The persistent store coordinator for the application. This implementation creates and return 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
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("MarathonRun")
var error: NSError? = nil
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: nil)
}catch let error as NSError {
coordinator = nil
// Report any error we got.
var dict = [AnyHashable: Any]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
print("Error: \(error.domain)")
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
if coordinator == nil {
return nil
}
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)//NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if let moc = self.managedObjectContext {
if moc.hasChanges{
do{
try moc.save()
}catch let error as NSError{
print("Error: \(error.domain)")
}
}
}
Please check screenshots
Your managedObjectContext object is nil and you have forced wrapped it with ! which will cause the crash.
So before you do this:
let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext!) as! Run
Make sure you have a value for managedObjectContext:
if let managedObjectContext = [get the managedObjectContext object here] {
// If you succeed with getting the managedObjectContext, then you can use it without the ! in here
let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext) as! Run
}
After doing some investigation by reading the comments the reason of the crash is most likely that you are only declaring the managed object context
var managedObjectContext: NSManagedObjectContext?
but not initializing it in the view controller. So it remains nil and causes the crash.
A suitable way to get the context from AppDelegate is a lazy instantiated property
lazy var managedObjectContext : NSManagedObjectContext = {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.managedObjectContext
}()
Now your saveRun() method is supposed to work.
By the way: Do not initialize persistentStoreCoordinator and managedObjectContext in AppDelegate as optional. That's nonsense. The app is unfeasible and will terminate anyway if the coordinator could not be created.
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("MarathonRun")
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
} catch let error as NSError {
// Report any error we got.
var dict = [AnyHashable: Any]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = "There was an error creating or loading the application's saved data."
dict[NSUnderlyingErrorKey] = error
print("Error: ", error)
abort()
}
return coordinator
}()
lazy var managedObjectContext: NSManagedObjectContext = {
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)//NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
Another cumbersome code is the dance to convert Double to NSNumber and vice versa. It's perfectly legal to declare latitude and longitude in the NSManagedObject subclass as Double. Same thing are date attributes. Declare them as Date to avoid a lot of type casting.
you can use if let ,So you app will not crash.
if let savedRun = NSEntityDescription.insertNewObject(forEntityName: "Run", into: managedObjectContext!) as! Run {
}
But for permanent fix, Please recheck for Run Entity class.
Good morning,
I'm working for the first time using CoreData with Swift 2.2. At the moment, I can add objects to my entity "Item" and I can remove all the items after I press a button "Remove everything". That's correct, but when I delete all the objects and then I restart my app, I still have the same Core Data before the "Remove everything" action.
That's how I delete the Core Data objects:
#IBAction func removeWishlist(sender: AnyObject) {
deleteAllData("ItemsWishlist")
getWishlist()
self.tableView.reloadData()
}
func deleteAllData(entity: String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedContext.executeFetchRequest(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.deleteObject(managedObjectData)
print("Deleted")
}
} catch let error as NSError {
print(error)
}
}
And it's working because when I press the button, the list is empty, but when I restart the app, it shows again the same items as before I pressed the "clear" button.
And that's my AppDelegate with the Core Data part:
// 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 "-.test" 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("wishlist", 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()
}
}
}
What am I doing wrong with the Core Data? How can I resolve this issue?
Much appreciated,
Regards.
The reason why you got those objects back after restarting your app is because you did not save your NSManagedObjectContext after performing all the deletion so that those changes can be persisted to the persistence store you are using.
The context is like a virtual board. Think of your managed objects on a context as toys that you put on a table to play with. You can move them around, break them, move them out of the table, and bring new toys in. That table is your managed object context, and you can save its state when you are ready. When you save the state of the managed object context, this save operation will be communicated to the persistent store coordinator to which the context is connected. Then the persistent store coordinator will store the information to the persistent store and subsequently to disk.
func deleteAllData(entity: String) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedContext.executeFetchRequest(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.deleteObject(managedObjectData)
print("Deleted")
}
} catch let error as NSError {
print(error)
}
appDelegate.saveContext()
}
For performance benefits, you should look into NSBatchDeleteRequest.
I have started learning core data in iOS now. I am currently getting fatal error: unexpectedly found nil while unwrapping an Optional value on the line of code below. I have been following lectures on youtube and few other places and had a look at their code too but failed to know the reason behind this error. If someone could provide me with an overview of it will be really helpful. Currently in my code I am just assigning values from entity, no fetching.
App Delegate:
lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "com.alakh.singh.okejhbs" 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("ActivityMonitor", 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()
}
}
}
}
ViewController:
#IBAction func cofirmLogin(sender: UIButton) {
let oct = ((UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext)
var userNameValue = NSEntityDescription.insertNewObjectForEntityForName("LoginInformation", inManagedObjectContext: oct!) as! LoginInformation
userNameValue.loginUserName = loginUserName.text!
userNameValue.loginPin = Int(loginPin.text!)!
userNameValue = loginInfo
saveContext(oct!)
}
func saveContext (context : NSManagedObjectContext) {
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
Maybe something is not working as expected with the lazy variable. You could refactor your managed object context like this.
var managedObjectContext: NSManagedObjectContext {
get {
if _managedObjectContext == nil {
let coordinator = self.persistentStoreCoordinator
let moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
moc.persistentStoreCoordinator = coordinator
_managedObjectContext = moc
}
return _managedObjectContext!
}
}
var _rootContext: NSManagedObjectContext?
Also, make sure that the app delegate is returned as expected (perhaps break this up into several lines and check in the debugger).
I try to create an APP with CoreData and CoreLocation.
CoreLocation works well, but CoreData always give me a fatal error : found nil while unwrapping an Option value every time that i load AppDelegate.
I print appDelegate and NSManagedObjectContext and return nil for both
This is my code into a ViewController
import UIKit
import CoreLocation
import CoreData
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var appDelegate :AppDelegate?
var context :NSManagedObjectContext?
var entitylUtenti :NSEntityDescription?
func loadCoreData() {
let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context : NSManagedObjectContext = appDelegate.managedObjectContext!
let entityUtenti = NSEntityDescription.entityForName("Utenti", inManagedObjectContext: context)
if(entitylUtenti == nil) {
println("vuoto")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
loadCoreData()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
}
In my AppDelegate.swift i insert
lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "xCodingIT.DiarioScolastico" in the application's documents Application Support directory.
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count-1] as! NSURL
}()
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("staffandstock", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
// The persistent store coordinator for the application. This implementation creates and return 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
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("staffandstock.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil {
coordinator = nil
// Report any error we got.
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as [NSObject : AnyObject])
// 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 \(error), \(error!.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
if coordinator == nil {
return nil
}
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving support
func saveContext () {
if let moc = self.managedObjectContext {
var error: NSError? = nil
if moc.hasChanges && !moc.save(&error) {
// 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.
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()
}
}
}
Anyone have an idea to resolve it ?
By redefining appDelegate & context in the function you're effectively 'shadowing' the instance variables:
func loadCoreData() {
// these two lines
let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context : NSManagedObjectContext = appDelegate.managedObjectContext!
Remove the let keyword and try again.
I resolve it !!!
I delete my function loadCoreData and insert into func viewDidLoad my appdelegate and my context without let.
I don't know why if i remove let from loadCoreData nothing change ... but now it works !!!