Unable to pass NSManagedObjectContext to my view controller - ios

Ok, I may be in well over my head here, but suspect I am missing something quite fundamental. I have searched on stack and other forums for help on finding a solution. I've tried all the solutions I have found but none work for my situation and I cannot see what I am missing.
I have created a CoreData app. All works fine in reading and writing data to the CoreData store using NSManagedObjectContext within my appDelegate. I have checked to see if the NSManagedObjectContext is set in my AppDelegate and it is. After passing it to my only viewController I check to see if it is set and it isn't. So that is clearly my issue. I have tried everything and cannot fathom the solution, now tired and want to go to bed. I'm pretty new to iOS, so I am sure it's something fundamental.
Here's my code as it stands.
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#import "Recipe.h"
#interface AppDelegate()
#property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (nonatomic, strong) ViewController *viewController;
#end
#implementation AppDelegate
#synthesize managedObjectModel, managedObjectContext, persistentStoreCoordinator, viewController;
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSManagedObjectContext *context = [self managedObjectContext];
if (!context) {
NSLog(#"There is an error!!!");
}
if (context == nil) {
NSLog(#"Context is nil in appdelegate");
}
else {
NSLog(#"Context is set in appdelegate");
}
viewController.managedObjectContext = self.managedObjectContext;
// Override point for customization after application launch.
return YES;
}
#pragma mark - Core Data
- (NSManagedObjectModel *)managedObjectModel
{
if (managedObjectModel == nil) {
NSString *modelPath = [[NSBundle mainBundle] pathForResource:#"RecipeBook" ofType:#"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return managedObjectModel;
}
- (NSString *)documentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return documentsDirectory;
}
- (NSString *)dataStorePath
{
return [[self documentsDirectory] stringByAppendingPathComponent:#"DataStore.sqlite"];
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (persistentStoreCoordinator == nil) {
NSURL *storeURL = [NSURL fileURLWithPath:[self dataStorePath]];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
NSError *error;
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Error adding persistent store %#, %#", error, [error userInfo]);
abort();
}
}
return persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext
{
if (managedObjectContext == nil) {
NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator;
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:coordinator];
}
}
return managedObjectContext;
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UITableViewController {
NSArray *recipes;
NSManagedObjectContext *managedObjectContext;
}
#property (nonatomic, retain) NSArray *recipes;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#end
ViewController.m
#import "ViewController.h"
#import "Recipe.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize recipes;
#synthesize managedObjectContext;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"View Did Load");
NSManagedObjectContext *context = [self managedObjectContext];
if (!context) {
NSLog(#"There is an error!!!");
}
if (context == nil) {
NSLog(#"Context is nil in viewController");
}
else {
NSLog(#"Context is set in viewController");
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
- (void)viewDidUnload {
[super viewDidUnload];
}
#end
I know the NSManagedObjectContext is nil in my ViewController. The question is how do I pass my context from AppDelegate into ViewController? I don't want to have to question the AppDelegate from my viewControllers (More will hopefully be added) every time I want to query CoreData, I'm looking to pass the managedObjectContext around.
I hope that all makes sense. :)

I have discovered the answer to my issue. The managedObjectContext wasn't being passed correctly to my viewController.
I was using:
viewController.managedObjectContext = self.managedObjectContext;
When I should have been using:
ViewController *viewController = (ViewController *)self.window.rootViewController;
viewController.managedObjectContext = self.managedObjectContext;
Thanks user523234 for putting me on the right lines.

Related

What is the best way to fetch data in core data between two regular view controllers?

Sorry if the title is bad. What I'm trying to understand is: in the core data examples I have found online they explain how to use core data with nsfetchresultcontroller. But from what I understand nsfetchresultcontroller is made for table views. But I have only 2 regular view controllers.
It's really basic, I have 1 view controller for a create page to create a task, and another one which is the homepage with a label to show that single task that was created:
HomePageViewController.m:
#import "HomePageViewController.h"
#import "CreatTargetViewController.h"
#interface HomePageViewController ()
#property (weak, nonatomic) IBOutlet UILabel *currentTarget;
#end
#implementation HomePageViewController
- (IBAction)unwindToHomePage:(UIStoryboardSegue *)segue
{
CreatTargetViewController *source = (CreatTargetViewController *)[segue sourceViewController];
self.currentTarget.text = source.target.content;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
CreatTargetViewController.h:
#import <UIKit/UIKit.h>
#import "Targets.h"
#interface CreatTargetViewController : UIViewController
#property (nonatomic, strong) Targets *target;
#end
CreatTargetViewController.m:
#import "CreatTargetViewController.h"
#import "Targets.h"
#import "CoreDataStack.h"
#interface CreatTargetViewController ()
#property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton;
#property (weak, nonatomic) IBOutlet UITextView *myTextView;
#end
#implementation CreatTargetViewController
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (sender != self.saveButton) return;
if (self.target != nil) {
self.myTextView.text = self.target.content;
}
}
- (void)insertNewTargetEntry
{
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
Targets *entry = [NSEntityDescription insertNewObjectForEntityForName:#"Targets" inManagedObjectContext:coreDataStack.managedObjectContext];
entry.content = self.myTextView.text;
[coreDataStack saveContext];
}
- (void)updateTargetEntry
{
self.target.content = self.myTextView.text;
CoreDataStack *stack = [CoreDataStack defaultStack];
[stack saveContext];
}
- (IBAction)saveWasPressed:(id)sender
{
if (self.target != nil) {
[self updateTargetEntry];
} else {
[self insertNewTargetEntry];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[self.myTextView becomeFirstResponder];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
and another class for the core data stack:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface CoreDataStack : NSObject
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
+ (instancetype)defaultStack;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
CoreDataStack.m:
#import "CoreDataStack.h"
#implementation CoreDataStack
#pragma mark - Core Data stack
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
+ (instancetype)defaultStack
{
static CoreDataStack *defaultStack;
static dispatch_once_t onceToken;
dispatch_once (&onceToken, ^{
defaultStack = [[self alloc] init];
});
return defaultStack;
}
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "digitalCrown.LaserApp" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"LaserApp" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"LaserApp.sqlite"];
NSError *error = nil;
NSString *failureReason = #"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = #"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:#"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 %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext 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();
}
}
}
How do I communicate the data here?

Multiple xcdatamodel files in Xcode

My project(for managing students' attendance in various classes) contains 2 xkcddatamodel files, one for the semester start/end dates and the other for the course data. If you look at AppDelegate.m, I've set the modelURL to the second model. How am I supposed to create a second context for the first xkcddatamodel? I've tried the solution given here. But no dice. Xcode isn't even recognising it and is asking me to replace managedObjectContext2 with managedObjectContext. How do I fix this?
Dropbox link to the project: https://www.dropbox.com/sh/ivl6nw6nw8p9j1y/MDwYDaHVH_
Here's the AppDelegate.m
//
// AppDelegate.m
// timetable app
//
// Created by Robin Malhotra on 22/12/13.
// Copyright (c) 2013 Robin's code kitchen. All rights reserved.
//
#import "AppDelegate.h"
#import <CoreData/CoreData.h>
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
// Explicitly write Core Data accessors
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
// removed some code about retain here as ARC hates that
return managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
stringByAppendingPathComponent: #"Courses.sqlite"]];
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"ClassesAttended" withExtension:#"momd"];
managedObjectModel=[[NSManagedObjectModel alloc]initWithContentsOfURL:modelURL];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeUrl options:nil error:&error]) {
/*Error for store creation should be handled in here*/
}
return persistentStoreCoordinator;
}
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
/* (...Existing Application Code...) */
-(NSArray *)getAllCourses
{
NSFetchRequest *request=[[NSFetchRequest alloc]init];
NSEntityDescription *entitydesc=[NSEntityDescription entityForName:#"Course" inManagedObjectContext:managedObjectContext];
[request setEntity:entitydesc];
NSError *error;
NSArray *fetchedCourses=[self.managedObjectContext executeFetchRequest:request error:&error];
return fetchedCourses;
}
#end
and here's the AppDelegate.h
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
}
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, readonly) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (nonatomic, readonly) NSManagedObjectModel *managedObjectModel2;
#property (nonatomic, readonly) NSManagedObjectContext *managedObjectContext2;
#property (nonatomic, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator2;
- (NSString *)applicationDocumentsDirectory;
- (NSArray *)getAllCourses;
#end

Trouble adding Core Data to a Storyboard App

I am having trouble adding a Core Data functionality to my app.
I cannot understand why managedObjectContext is always nil (even in my AppDelegate). I know that I should be passing it from the model, but and not sure how to do this.
I get the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Goal''
g4tappDelegate.h
#import <UIKit/UIKit.h>
#import "Goal.h"
#class g4tPopPageViewController;
#interface g4tAppDelegate : UIResponder <UIApplicationDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UIWindow *window;
}
- (NSManagedObjectContext *)managedObjectContext;
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) g4tPopPageViewController *PopPageViewController;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#end
g4tappDelegate.m
#import "g4tAppDelegate.h"
#import "g4tPopPageViewController.h"
#import "Goal.h"
#implementation g4tAppDelegate
NSManagedObjectContext *managedObjectContext;
#synthesize PopPageViewController;
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSManagedObject *newGoal;
//ERROR HERE
newGoal = [NSEntityDescription
insertNewObjectForEntityForName:#"Goal"
inManagedObjectContext:_managedObjectContext];
PopPageViewController.managedObjectContext = self.managedObjectContext;
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController* vc = [sb instantiateViewControllerWithIdentifier:#"AddGoal"];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
[self.window setRootViewController:navigationController];
[self.window makeKeyAndVisible];
// Override point for customization after application launch.
return YES;
}
Initialize your context first. Pass the context to the viewController instance first after creating it. Either you are missing some implementation or you didn't post it here.
Also, correct your property
#property (strong, nonatomic) PopPageViewController *g4tPopPageViewController;
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"YourStore.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
// Then pass it to your other controller from your viewDidLoad
vc.managedObjectContext = _managedObjectContext;

CoreData: nil is not a legal NSManagedObjectContext parameter

I am very new to Core Data and have been trying to following many tutorials, but most of them put all of the Core Data methods into AppDelegate. I have read that it is better to stay away from AppDelegate and use a custom Data Model class to manage these methods.
I have created a custom class to manage all of my data named MyDataModel. I implemented the boiler plate Core Data code. In one of my view controllers I have a simple method to implement some data using Core Data:
- (void)getProfile {
/*
* getProfile
*/
NSLog(#"%#", _Model.managedObjectContext);
Users *user = (Users *)[NSEntityDescription insertNewObjectForEntityForName:#"Users" inManagedObjectContext:_Model.managedObjectContext];
// Set Data
[user setValue:#"John" forKey:#"fname"];
[user setValue:#"Smith" forKey:#"lname"];
NSError *error;
[_Model.managedObjectContext save:&error];
}
The code from the header file:
#import <UIKit/UIKit.h>
#import "Users.h"
#import <CoreData/CoreData.h>
#import "DataModel.h"
#interface ProfileViewController : UIViewController
// CoreData Related
#property (strong, nonatomic) DataModel *Model;
// Instance Methods
- (void)updateProfileData;
// Core Data Method
- (void)getProfile;
#end
This method is called in the view controller's viewDidLoad method. When I run this, I get the following error:
'+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Users''
I have found a similar question here on StackOverflow that may help, but I still don't understand what the solution actually is.
'+entityForName: nil is not a legal NSManagedObjectContext parameter - Core Data
The stated solution from that thread was that he passed the context to the ViewController. How is this accomplished? I already thought I was doing that.
EDIT: DataModel.h:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Workouts.h"
#import "sqlite3.h"
#interface DataModel : NSObject {
sqlite3 *Database;
}
#property (nonatomic, strong) Workouts *currentWorkout;
// Core Data Properties
#property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, strong) NSPersistentStoreCoordinator *storeCoordinator;
+ (DataModel *)sharedInstance;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
DataModel.m:
#import "DataModel.h"
#implementation DataModel
#pragma mark - Core Data
+ (DataModel *)sharedInstance {
static DataModel *sharedModel = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedModel = [[DataModel alloc] init];
//sharedInstance.storeCoordinator = [sharedInstance storeCoordinator];
//sharedInstance.managedObjectContext = [sharedInstance managedObjectContext];
});
return sharedModel;
}
- (void)saveContext {
NSError *error = nil;
if (_managedObjectContext != nil) {
if ([_managedObjectContext hasChanges] && ![_managedObjectContext save:&error]) {
NSLog(#"error: %#", error.userInfo);
}
}
}
#pragma mark - Core Data Stack
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self storeCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return _managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"DataModel" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_storeCoordinator != nil) {
return _storeCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"model.sqlite"];
NSError *error = nil;
_storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_managedObjectModel];
if (![_storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
return _storeCoordinator;
}
#pragma mark Application's Documents Directory
- (NSURL *)applicationDocumentsDirectory {
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
UPDATE: I realize the reason why the objects were (null). I was trying to call the sharedInstance singleton method and they were not calling correctly. The getter was being called and would throw into a loop that would keep calling the getter. I correctly used the synthesized variables _managedObjectContext and _storeCoordinator. The objects now appropriately allocate memory and return the reference. Thanks for the help everyone.
There isn't anything wrong with the Core Data Stack being created in the Application Delegate. Where have you read that this is the case.
It's certainly considered bad design to be calling down to the Application Delegate to get the managed object context, but what most people do is to pass a reference to the managed object context from the Application Delegate to the other view controllers that use it.
Dumb question: Your model is in fact named DataModel?

"window" undeclared (first use in this function) error in iOS tutorial

I am trying the Core Data Tutorial and I have copied the code as given in this Apple's tutorial on Core Data here:
http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/iPhoneCoreData01/Articles/02_RootViewController.html
It asks us to compile and run after implementing the application delegate. When I do so, Xcode 4 compiler gives this error "window undeclared (first use in this function)". I can see that there is window declared as a property and there is a synthesize line in the code like so:
#synthesize window=_window;
so even though there is a window property declared in the program, why am I getting this error?
Here are the .h and .m files:
.h:
#import
#interface LocationsAppDelegate : NSObject <UIApplicationDelegate> {
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) UINavigationController *navigationController;
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
#property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
Now for the .m file:
#import "LocationsAppDelegate.h"
#import "RootViewController.h"
#implementation LocationsAppDelegate
#synthesize navigationController;
#synthesize window=_window;
#synthesize managedObjectContext=__managedObjectContext;
#synthesize managedObjectModel=__managedObjectModel;
#synthesize persistentStoreCoordinator=__persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
NSManagedObjectContext *context = [self managedObjectContext];
if(!context) {
//handle the error you dummy!!
}
rootViewController.managedObjectContext = context;
UINavigationController *aNavigationController = [[UINavigationController alloc]initWithRootViewController:rootViewController];
self.navigationController = aNavigationController;
[self.window addSubview:[navigationController view]];
[self.window makeKeyAndVisible];
[rootViewController release];
[aNavigationController release];
return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application
{
[self saveContext];
}
- (void)dealloc
{
[_window release];
[__managedObjectContext release];
[__managedObjectModel release];
[__persistentStoreCoordinator release];
[super dealloc];
}
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil)
{
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil)
{
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil)
{
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Locations" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Locations.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
Try to use
self.window
instead of
window
Just to expand on that answer a bit:
You can see from the #synthesize statement that the property window is backed by the instance variable _window. So you use window to access it via the getter (self.window or [self window]), but if you're trying to access the instance variable directly, it would be _window.

Resources