Core Data to SQL not working - iphone

I have been trying like hell to figure out how to establish a connection between my Core Data & my SQL database. The database isn't pre-populated, but it will be used amongst many different users when it's launched.
I have gone through the Core Data & iCloud classes provided by Stanford three times to no avail. I have also looked throughly into SQLite/SQL relational databases in iOS to no avail. The only other option I have is to come on here, post all the code I can, and pray that somebody will have an answer for me. So here it goes...
AppDelegate.m
- (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 = [self applicationDocumentsDirectory];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"shindy.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
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"shindy.sqlite"];
return [NSURL fileURLWithPath:path];
}
HomeViewController.m
- (void)setupFetchedResultsController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"dateAndTime" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"photo" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"timePosted" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"location" ascending:YES],
nil];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.shindyDatabase.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
- (void)fetchShindyDataIntoDocument:(UIManagedDocument *)document
{
dispatch_queue_t fetchQ = dispatch_queue_create("Shindy Fetcher", nil);
dispatch_async(fetchQ, ^{
NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSLog(#"shindys = %#", shindys);
[document.managedObjectContext performBlock:^{
for (NSDictionary *shindyInfo in shindys) {
[Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:document.managedObjectContext];
NSLog(#"fire");
}
}];
});
}
- (void)useDocument
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"shindy.sqlite"];
if (![[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil]) {
[self.shindyDatabase saveToURL:self.shindyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self setupFetchedResultsController];
[self fetchShindyDataIntoDocument:self.shindyDatabase];
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateClosed) {
[self.shindyDatabase openWithCompletionHandler:^(BOOL success) {
[self setupFetchedResultsController];
}];
} else if (self.shindyDatabase.documentState == UIDocumentStateNormal) {
[self setupFetchedResultsController];
}
}
- (void)setShindyDatabase:(UIManagedDocument *)shindyDatabase
{
[self useDocument];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self fetchShindyDataIntoDocument:self.shindyDatabase];
if (!self.shindyDatabase) {
[self setShindyDatabase:self.shindyDatabase];
}
}
Shindy+ShindyDB.m
+ (Shindy *)shindyWithShindyDBInfo:(NSDictionary *)shindyInfo
inManagedObjectContext:(NSManagedObjectContext *)context
{
Shindy *shindy = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Shindy"];
NSSortDescriptor *dateAndTimeSort = [NSSortDescriptor sortDescriptorWithKey:#"dateAndTime" ascending:YES];
NSSortDescriptor *detailsSort = [NSSortDescriptor sortDescriptorWithKey:#"details" ascending:YES];
NSSortDescriptor *locationSort = [NSSortDescriptor sortDescriptorWithKey:#"location" ascending:YES];
NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
NSSortDescriptor *photoSort = [NSSortDescriptor sortDescriptorWithKey:#"photo" ascending:YES];
NSSortDescriptor *timePostedSort = [NSSortDescriptor sortDescriptorWithKey:#"timePosted" ascending:YES];
// title
request.sortDescriptors = [NSArray arrayWithObjects:dateAndTimeSort, detailsSort, locationSort, nameSort, photoSort, timePostedSort, nil];
NSError *error = nil;
NSArray *matches = [context executeFetchRequest:request error:&error];
if (!matches || ([matches count] > 1)) {
// handle error
} else if ([matches count] == 0) {
shindy = [NSEntityDescription insertNewObjectForEntityForName:#"Shindy" inManagedObjectContext:context];
shindy.dateAndTime = [shindyInfo objectForKey:#"dateAndTime"];
shindy.details = [shindyInfo objectForKey:#"details"];
shindy.location = [shindyInfo objectForKey:#"location"];
shindy.name = [shindyInfo objectForKey:#"name"];
shindy.photo = [shindyInfo objectForKey:#"photo"];
shindy.timePosted = [shindyInfo objectForKey:#"timePosted"];
// title
// Guestlist? The rest?
// Use below for reference
shindy.whoseShindy = [User userWithName:[shindyInfo objectForKey:#"whoseShindy"] inManagedObjectContext:context];
} else {
shindy = [matches lastObject];
}
shindy = [NSEntityDescription insertNewObjectForEntityForName:#"Shindy" inManagedObjectContext:context];
shindy.dateAndTime = [shindyInfo objectForKey:#"dateAndTime"];
shindy.details = [shindyInfo objectForKey:#"details"];
shindy.location = [shindyInfo objectForKey:#"location"];
shindy.name = [shindyInfo objectForKey:#"name"];
shindy.photo = [shindyInfo objectForKey:#"photo"];
shindy.timePosted = [shindyInfo objectForKey:#"timePosted"];
return shindy;
}
AddShindyViewController.m
- (void)saveShindyToDatabase
{
NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
[self.shindyDatabase.managedObjectContext performBlock:^{
for (NSDictionary *shindyInfo in shindys) {
[Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:self.shindyDatabase.managedObjectContext];
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
// url = [url URLByAppendingPathComponent:#"Default Shindy Database"];
self.shindyDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
[self.shindyDatabase setValue:self.detailView.text forKey:#"details"];
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
self.name = user.name;
self.photo.profileID = user.id;
self.username = user.username;
}
}];
}
[self.shindyDatabase setValue:self.name forKey:#"name"];
[self.shindyDatabase setValue:self.photo forKey:#"photo"];
[self.shindyDatabase setValue:self.username forKey:#"username"];
// [Guest guestWithName:self.name username:self.username photo:self.photo inManagedObjectContext:self.shindyDatabase.managedObjectContext];
[self.shindyDatabase setValue:self.locationManager.location forKey:#"location"];
[self.shindyDatabase setValue:self.dateAndTimePicker.date forKey:#"dateAndTime"];
}
}];
}
I know what I'm asking for is a hell of a lot, but I have exhausted every single resource I have at my disposal. If anybody can even just point me in the right direction, I would be eternally grateful!

If you plan to map an existing database with CoreData you will be unsuccessful.
There's infact no way you can map any database with CoreData.
Core Data infact is a graph object management, with different storage option, and sqllite is just one of the possibility. At startup, if you choose sqllite as option, your application is going to create a database with a specific tables structure. If you try to connect to a database not created by CoreData framework you will get an error.
What you can do is get rid of CoreData, and build your NSObject to act like entities. But then, you will have to implement all the logic to save, update, versioning, concurrency ecc... and it's a long (and buggy) way, especially in a multi user environment.
Otherwise, tell me if I misunderstood your question. Maybe, you can post an error stack trace.

Related

Table view and Predicates

I have a table view with 40 objects. I have to filter them by gender when Click in a UISegment (male, female and both). It seems to be working, but table view does not refresh. Please any help would be appreciatte.
-(void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"People";
[self loadall];
[[NSBundle mainBundle] loadNibNamed:#"FilterSortView" owner:self options:nil];
self.filterControl.selectedSegmentIndex = -1;
[self.filterControl addTarget:self action:#selector( changeSegge ) forControlEvents:UIControlEventValueChanged];
}
#
My second method to filter by gender
- (void)changeSegge
{
NSEntityDescription *personEntity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:personEntity];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
if (error)
{
[NSException raise:NSInternalInconsistencyException format:#"Could not fetch Core Data records: %#",error];
}
if(filterControl.selectedSegmentIndex == 0){
NSPredicate *predicatem =[NSPredicate predicateWithFormat:#"gender == %#", #"m" ];
request.predicate=predicatem;
[self.tableView reloadData];
[request release];
NSLog(#"button 1");
}
Thanks a lot.
You forgot to fill people array after predicate set to fetch request.
Here is updated changeSegge method:
- (void)changeSegge
{
NSEntityDescription *personEntity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:personEntity];
NSError *error = nil;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
if (error)
{
[NSException raise:NSInternalInconsistencyException format:#"Could not fetch Core Data >records: %#",error];
}
if(filterControl.selectedSegmentIndex == 0){
NSPredicate *predicatem =[NSPredicate predicateWithFormat:#"gender == %#", #"m" ];
request.predicate=predicatem;
self.people = [self.managedObjectContext executeFetchRequest:request error:&error];
[self.tableView reloadData];
[request release];
NSLog(#"button 1");
}

Syncing Data with Parse, not downloading data

I have been following the How To Synchronize Core Data with a Web Service – Part 1 from RayWenderlinch.com I am trying to customize it to my application and have an issue with the actual downloading of the data from Parse using AFNetworking
The application should connect to parse, see the two classes "Club" and "IronSet" check and see if there are and new records (or on initial run, grab everything) and download only the newly added stuff.
Then it will save those records to core data, then delete the files from the Cache/JSONRecords/Club(or IronSet). It seems I am never actually grabbing the data from Parse, although it is connecting successfully, and does not throw an error until it goes to delete the the files from the Cache.
I am getting the "All operations completed" indicating the SyncEngine should be complete with the download in the downloadDataForRegisteredObjects
Error
2013-08-26 19:39:03.981 WGT Golf Calculator[3287:c07] All operations completed
2013-08-26 19:39:03.991 WGT Golf Calculator[3287:c07] Unable to delete JSON records at Club -- file://localhost/Users/**/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/4B72F57E-264D-44F7-981D-3D921B0CC2A4/Library/Caches/JSONRecords/, reason Error Domain=NSCocoaErrorDomain Code=4 "The operation couldn’t be completed. (Cocoa error 4.)" UserInfo=0x75610f0 {NSUnderlyingError=0x75615e0 "The operation couldn’t be completed. No such file or directory", NSFilePath=/Users/**/Library/Application Support/iPhone Simulator/6.1/Applications/4B72F57E-264D-44F7-981D-3D921B0CC2A4/Library/Caches/JSONRecords/Club, NSUserStringVariant=(
Remove
)}
MLVAppDelegate.m
#import "MLVAppDelegate.h"
#import "MLVSyncEngine.h"
#import "Club.h"
#import "IronSet.h"
#implementation MLVAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[Club class]];
[[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[IronSet class]];
return YES;
}
MLVAFParseAPIClient.h
#import "AFHTTPClient.h"
#interface MLVAFParseAPIClient : AFHTTPClient
+ (MLVAFParseAPIClient *)sharedClient;
- (NSMutableURLRequest *)GETRequestForClass:(NSMutableString *)className parameters:(NSDictionary *)parameters;
- (NSMutableURLRequest *)GETRequestForAllRecordsOfClass:(NSString *)className updatedAfterDate:(NSDate *)updatedDate;
#end
MLVAFParseAPIClient.m
#import "MLVAFParseAPIClient.h"
#import "AFJSONRequestOperation.h"
static NSString * const kSDFParseAPIBaseURLString = #"https://api.parse.com/1/";
static NSString * const kSDFParseAPIApplicationId = #"APP ID REMOVED";
static NSString * const kSDFParseAPIKey = #"API KEY REMOVED";
#implementation MLVAFParseAPIClient
+ (MLVAFParseAPIClient *)sharedClient
{
static MLVAFParseAPIClient *sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{sharedClient = [[MLVAFParseAPIClient alloc] initWithBaseURL:[NSURL URLWithString:kSDFParseAPIBaseURLString]];
});
return sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (self) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setParameterEncoding:AFJSONParameterEncoding];
[self setDefaultHeader:#"X-Parse-Application-Id" value:kSDFParseAPIApplicationId];
[self setDefaultHeader:#"X-Parse-REST-API-Key" value:kSDFParseAPIKey];
}
return self;
}
- (NSMutableURLRequest *)GETRequestForClass:(NSMutableString *)className parameters:(NSDictionary *)parameters
{
NSMutableURLRequest *request = nil;
request = [self requestWithMethod:#"GET" path:[NSString stringWithFormat:#"classes/%#", className] parameters:parameters ];
return request;
}
- (NSMutableURLRequest *)GETRequestForAllRecordsOfClass:(NSString *)className updatedAfterDate:(NSDate *)updatedDate
{
NSMutableURLRequest *request = nil;
NSDictionary *parameters = nil;
if (updatedDate) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.'999Z'"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSString *jsonString = [NSString stringWithFormat:#"{\"updatedAt\":{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%#\"}}}", [dateFormatter stringFromDate:updatedDate]];
parameters = [NSDictionary dictionaryWithObject:jsonString forKey:#"where"];
}
request = [self GETRequestForClass:className parameters:parameters];
return request;
}
#end
MLVCoreDataController.m
#import "MLVCoreDataController.h"
#interface MLVCoreDataController ()
#property (strong, nonatomic) NSManagedObjectContext *masterManagedObjectContext;
#property (strong, nonatomic) NSManagedObjectContext *backgroundManagedObjectContext;
#property (strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#end
#implementation MLVCoreDataController
#synthesize masterManagedObjectContext = _masterManagedObjectContext;
#synthesize backgroundManagedObjectContext = _backgroundManagedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
+ (id)sharedInstance {
static dispatch_once_t once;
static MLVCoreDataController *sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
#pragma mark - Core Data stack
// Used to propegate saves to the persistent store (disk) without blocking the UI
- (NSManagedObjectContext *)masterManagedObjectContext {
if (_masterManagedObjectContext != nil) {
return _masterManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_masterManagedObjectContext performBlockAndWait:^{
[_masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
}];
}
return _masterManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)backgroundManagedObjectContext {
if (_backgroundManagedObjectContext != nil) {
return _backgroundManagedObjectContext;
}
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
_backgroundManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundManagedObjectContext performBlockAndWait:^{
[_backgroundManagedObjectContext setParentContext:masterContext];
}];
}
return _backgroundManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)newManagedObjectContext {
NSManagedObjectContext *newContext = nil;
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[newContext performBlockAndWait:^{
[newContext setParentContext:masterContext];
}];
}
return newContext;
}
- (void)saveMasterContext {
[self.masterManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.masterManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
NSLog(#"Could not save master context due to %#", error);
}
}];
}
- (void)saveBackgroundContext {
[self.backgroundManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.backgroundManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
NSLog(#"Could not save background context due to %#", error);
}
}];
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"WGTCalculator" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"WGTCalcul.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
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
MLVSyncEngine.h
#import <Foundation/Foundation.h>
typedef enum {
MLVObjectSynced = 0,
MLVObjectCreated,
MLVObjectDeleted,
} MLVObjectSyncStatus;
#interface MLVSyncEngine : NSObject
#property (atomic, readonly) BOOL syncInProgress;
+ (MLVSyncEngine *)sharedEngine;
- (void)registerNSManagedObjectClassToSync:(Class)aClass;
- (void)startSync;
#end
MLVSyncEngine.m
#import "MLVSyncEngine.h"
#import "MLVCoreDataController.h"
#import "MLVAFParseAPIClient.h"
#import "AFHTTPRequestOperation.h"
#import "AFJSONRequestOperation.h"
NSString * const kMLVSyncEngineInitialCompleteKey = #"MLVSyncEngineInitialSyncCompleted";
NSString * const kMLVSyncEngineSyncCompletedNotificationName = #"MLVSyncEngineSyncCompleted";
#interface MLVSyncEngine ()
#property (nonatomic, strong) NSMutableArray *registeredClassesToSync;
#property (nonatomic, strong) NSDateFormatter *dateFormatter;
#end
#implementation MLVSyncEngine
#synthesize registeredClassesToSync = _registeredClassesToSync;
#synthesize syncInProgress = _syncInProgress;
#synthesize dateFormatter = _dateFormatter;
+ (MLVSyncEngine *)sharedEngine
{
static MLVSyncEngine *sharedEngine = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedEngine = [[MLVSyncEngine alloc] init];
});
return sharedEngine;
}
- (void)registerNSManagedObjectClassToSync:(Class)aClass
{
if (!self.registeredClassesToSync) {
self.registeredClassesToSync = [NSMutableArray array];
}
if ([aClass isSubclassOfClass:[NSManagedObject class]]) {
if (![self.registeredClassesToSync containsObject:NSStringFromClass(aClass)]) {
[self.registeredClassesToSync addObject:NSStringFromClass(aClass)];
} else {
NSLog(#"Unable to register %# as it is already registered", NSStringFromClass(aClass));
}
} else {
NSLog(#"Unable to reguster %# as it is not a subclass of NSManagedObject", NSStringFromClass(aClass));
}
}
- (BOOL)initialSyncComplete{
return [[[NSUserDefaults standardUserDefaults] valueForKey:kMLVSyncEngineInitialCompleteKey] boolValue];
}
- (void)setInitialSyncCompleted{
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kMLVSyncEngineInitialCompleteKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)executeSyncCompletedOperations {
dispatch_async(dispatch_get_main_queue(), ^{
[self setInitialSyncCompleted];
NSError *error = nil;
[[MLVCoreDataController sharedInstance] saveBackgroundContext];
if (error) {
NSLog(#"Error saving background context after creating objects on server: %#", error);
}
[[MLVCoreDataController sharedInstance] saveMasterContext];
[[NSNotificationCenter defaultCenter]
postNotificationName:kMLVSyncEngineSyncCompletedNotificationName
object:nil];
[self willChangeValueForKey:#"syncInProgress"];
_syncInProgress = NO;
[self didChangeValueForKey:#"syncInProgress"];
});
}
- (void)startSync
{
if (!self.syncInProgress) {
[self willChangeValueForKey:#"syncInProgress"];
_syncInProgress = YES;
[self didChangeValueForKey:#"syncInProgress"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{[self downloadDataForRegisteredObjects:YES];
});
}
}
- (NSDate *)mostRecentUpdatedAtDateForEntityWithName:(NSString *)entityName {
__block NSDate *date = nil;
//
// Create a new fetch request for the specified entity
//
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
//
// Set the sort descriptors on the request to sort by updatedAt in descending order
//
[request setSortDescriptors:[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"updatedAt" ascending:NO]]];
//
// You are only interested in 1 result so limit the request to 1
//
[request setFetchLimit:1];
[[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext] performBlockAndWait:^{
NSError *error = nil;
NSArray *results = [[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext] executeFetchRequest:request error:&error];
if ([results lastObject]) {
//
// Set date to the fetched result
//
date = [[results lastObject] valueForKey:#"updatedAt"];
}
}];
return date;
}
- (void)newManagedObjectWithClassName:(NSString *)className forRecord:(NSDictionary *)record {
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:className inManagedObjectContext:[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext]];
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[self setValue:obj forKey:key forManagedObject:newManagedObject];
}];
[record setValue:[NSNumber numberWithInt:MLVObjectSynced] forKey:#"syncStatus"];
}
- (void)updateManagedObject:(NSManagedObject *)managedObject withRecord:(NSDictionary *)record {
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[self setValue:obj forKey:key forManagedObject:managedObject];
}];
}
- (void)setValue:(id)value forKey:(NSString *)key forManagedObject:(NSManagedObject *)managedObject {
if ([key isEqualToString:#"createdAt"] || [key isEqualToString:#"updatedAt"]) {
NSDate *date = [self dateUsingStringFromAPI:value];
[managedObject setValue:date forKey:key];
} else if ([value isKindOfClass:[NSDictionary class]]) {
if ([value objectForKey:#"__type"]) {
NSString *dataType = [value objectForKey:#"__type"];
if ([dataType isEqualToString:#"Date"]) {
NSString *dateString = [value objectForKey:#"iso"];
NSDate *date = [self dateUsingStringFromAPI:dateString];
[managedObject setValue:date forKey:key];
} else if ([dataType isEqualToString:#"File"]) {
NSString *urlString = [value objectForKey:#"url"];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *dataResponse = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[managedObject setValue:dataResponse forKey:key];
} else {
NSLog(#"Unknown Data Type Received");
[managedObject setValue:nil forKey:key];
}
}
} else {
[managedObject setValue:value forKey:key];
}
}
- (NSArray *)managedObjectsForClass:(NSString *)className withSyncStatus:(MLVObjectSyncStatus)syncStatus {
__block NSArray *results = nil;
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"syncStatus = %d", syncStatus];
[fetchRequest setPredicate:predicate];
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
return results;
}
- (NSArray *)managedObjectsForClass:(NSString *)className sortedByKey:(NSString *)key usingArrayOfIds:(NSArray *)idArray inArrayOfIds:(BOOL)inIds {
__block NSArray *results = nil;
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
NSPredicate *predicate;
if (inIds) {
predicate = [NSPredicate predicateWithFormat:#"objectId IN %#", idArray];
} else {
predicate = [NSPredicate predicateWithFormat:#"NOT (objectId IN %#)", idArray];
}
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"objectId" ascending:YES]]];
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
return results;
}
- (void)downloadDataForRegisteredObjects:(BOOL)useUpdatedAtDate {
NSMutableArray *operations = [NSMutableArray array];
for (NSString *className in self.registeredClassesToSync) {
NSDate *mostRecentUpdatedDate = nil;
if (useUpdatedAtDate) {
mostRecentUpdatedDate = [self mostRecentUpdatedAtDateForEntityWithName:className];
}
NSMutableURLRequest *request = [[MLVAFParseAPIClient sharedClient]
GETRequestForAllRecordsOfClass:className
updatedAfterDate:mostRecentUpdatedDate];
AFHTTPRequestOperation *operation = [[MLVAFParseAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
[self writeJSONResponse:responseObject toDiskForClassWithName:className];
NSLog(#"Response for %#: %#", className, responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Request for class %# failed with error: %#", className, error);
}];
[operations addObject:operation];
}
[[MLVAFParseAPIClient sharedClient] enqueueBatchOfHTTPRequestOperations:operations progressBlock:^(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations) {
} completionBlock:^(NSArray *operations) {
NSLog(#"All operations completed");
[self processJSONDataRecordsIntoCoreData];
}];
}
- (void)processJSONDataRecordsIntoCoreData {
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
//
// Iterate over all registered classes to sync
//
for (NSString *className in self.registeredClassesToSync) {
if (![self initialSyncComplete]) {
NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
NSArray *records = [JSONDictionary objectForKey:#"results"];
for (NSDictionary *record in records) {
[self newManagedObjectWithClassName:className forRecord:record];
}
} else {
NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:#"objectId"];
if ([downloadedRecords lastObject]) {
NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:#"objectId" usingArrayOfIds:[downloadedRecords valueForKey:#"objectId"] inArrayOfIds:YES];
int currentIndex = 0;
for (NSDictionary *record in downloadedRecords) {
NSManagedObject *storedManagedObject = nil;
if ([storedRecords count] > currentIndex) {
storedManagedObject = [storedRecords objectAtIndex:currentIndex];
}
if ([[storedManagedObject valueForKey:#"objectId"] isEqualToString:[record valueForKey:#"objectId"]]) {
[self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record];
} else {
[self newManagedObjectWithClassName:className forRecord:record];
}
currentIndex++;
}
}
}
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
if (![managedObjectContext save:&error]) {
NSLog(#"Unable to save context for class %#", className);
}
}];
[self deleteJSONDataRecordsForClassWithName:className];
[self executeSyncCompletedOperations];
}
}
- (void)initializeDateFormatter {
if (!self.dateFormatter) {
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
[self.dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
}
}
- (NSDate *)dateUsingStringFromAPI:(NSString *)dateString {
[self initializeDateFormatter];
dateString = [dateString substringWithRange:NSMakeRange(0, [dateString length]-5)];
return [self.dateFormatter dateFromString:dateString];
}
- (NSString *)dateStringForAPIUsingDate:(NSDate *)date {
[self initializeDateFormatter];
NSString *dateString = [self.dateFormatter stringFromDate:date];
dateString = [dateString substringWithRange:NSMakeRange(0, [dateString length]-1)];
dateString = [dateString stringByAppendingFormat:#".000Z"];
return dateString;
}
#pragma mark - File Management
- (NSURL *)applicationCacheDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSURL *)JSONDataRecordsDirectory{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *url = [NSURL URLWithString:#"JSONRecords/" relativeToURL:[self applicationCacheDirectory]];
NSError *error = nil;
if (![fileManager fileExistsAtPath:[url path]]) {
[fileManager createDirectoryAtPath:[url path] withIntermediateDirectories:YES attributes:nil error:&error];
}
return url;
}
-(void)writeJSONResponse:(id)response toDiskForClassWithName:(NSString *)className{
NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]] ;
if (![(NSDictionary *)response writeToFile:[fileURL path] atomically:YES]) {
NSLog(#"Error saving response to disk, will attempt to remove NSNull values and try again.");
//remove NSNulls and try again...
NSArray *records = [response objectForKey:#"results"];
NSMutableArray *nullFreeRecords = [NSMutableArray array];
for (NSDictionary *record in records) {
NSMutableDictionary *nullFreeRecord = [NSMutableDictionary dictionaryWithDictionary:record];
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSNull class]]) {
[nullFreeRecord setValue:nil forKey:key];
}
}];
[nullFreeRecords addObject:nullFreeRecord];
}
NSDictionary *nullFreeDictionary = [NSDictionary dictionaryWithObject:nullFreeRecords forKey:#"results"];
if (![nullFreeDictionary writeToFile:[fileURL path] atomically:YES]) {
NSLog(#"Failed all attempts to save response to disk: %#", response);
}
}
}
- (void)deleteJSONDataRecordsForClassWithName:(NSString *)className {
NSURL *url = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];
NSError *error = nil;
BOOL deleted = [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
if (!deleted) {
NSLog(#"Unable to delete JSON records at %#, reason %#", url, error);
}
}
- (NSDictionary *)JSONDictionaryForClassWithName:(NSString *)className {
NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];
return [NSDictionary dictionaryWithContentsOfURL:fileURL];
}
- (NSArray *)JSONDataRecordsForClass:(NSString *)className sortedByKey:(NSString *)key {
NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
NSArray *records = [JSONDictionary objectForKey:#"results"];
return [records sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:key ascending:YES]]];
}
#end
Honestly, if your data model is that simple, and you're deleting the local persistent store / cache on every load, you probably would be much better off not using Core Data.
Keep it simple by loading data as needed. Save a cache using NSCoding, to be loaded initially as a placeholder, while the app waits for new information to be downloaded.
So it turns out the answer was pretty straight forward, the tutorial uses an older Version of AFNetworking where AFHTTPRequestOperation can download the data but does not see it as JSON.
AFHTTPRequestOperation *operation = [[MLVAFParseAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
[self writeJSONResponse:responseObject toDiskForClassWithName:className];
NSLog(#"Response for %#: %#", className, responseObject);
}
}
Needed to be updated with AFJSONRequestOperation
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest: request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSDictionary * responseObject = (NSDictionary * )JSON;
if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSLog(#"Response for %#: %#", className, responseObject);
[self writeJSONResponse:responseObject toDiskForClassWithName:className];

CoreData inserting very huge DB exc_bad_access

I have ~60000 values in my DB.
I must to keep them all. But while inserting values I get exc_bad_access.
Here is my code:
if (context == nil)
{
context = [(radioAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", context);
}
[self performSelectorOnMainThread:#selector(deleteAllFromDB) withObject:nil waitUntilDone:YES];
// here is JSON parsing
int i=0;
#synchronized(self)
{
NSLog(#"Start");
NSEntityDescription *entity = [[NSEntityDescription entityForName:#"Station" inManagedObjectContext:context] autorelease];
for (NSString*string in stations)
{
if (![string isEqualToString:#""])
{
Station*station = [[[Station alloc] initWithEntity:entity insertIntoManagedObjectContext:nil] retain];
NSError *err = nil;
id parsedData = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers error:&err];
if (err) {
NSLog(#"error is %#", [err localizedDescription]);
}
[station setName:[parsedData objectForKey:#"nm"]];
[station setBit: [parsedData objectForKey:#"btr"]];
[station setEnabled: [NSNumber numberWithInt:1]];
//encoding id of the station
scanner = [NSScanner scannerWithString:[parsedData objectForKey:#"id"]];
[scanner scanHexInt:&tempInt];
NSNumber *numb = [[NSNumber alloc]initWithInt:i];
[station setNumber: [NSNumber numberWithInt:[numb intValue]]];
//encoding country ID
numb = [NSNumber numberWithInt:i];
[station setCountryID: [NSNumber numberWithInt:[numb intValue]]];
//encoding genre ID
numb = [NSNumber numberWithInt:i];
[station setGenerID:[NSNumber numberWithInt:[numb intValue]]];
[station setOrder:[NSNumber numberWithInt:i]];
[context insertObject:station];
float k = [stations count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
i++;
[scanner release];
[numb release];
[station release];
[parsedData release];
}
}
[context save:nil];
[entity release];
NSLog(#"Stop");
NSEntityDescription *entityGen = [NSEntityDescription entityForName:#"Genre" inManagedObjectContext:context];
NSURL* urlForGenre = [NSURL URLWithString:#"xxx.xxx"];
NSData *genres = [[NSData alloc] initWithContentsOfURL:urlForGenre];
NSError *err = nil;
NSArray *parsedGenres = [NSJSONSerialization JSONObjectWithData:genres options:NSJSONReadingMutableContainers error:&err];
if (err)
{
NSLog(#"error is %#", [err localizedDescription]);
}
for (int i =0; i<parsedGenres.count; i++)
{
Genre*gen = [[Genre alloc] initWithEntity:entityGen insertIntoManagedObjectContext:nil];
gen.name = [[parsedGenres objectAtIndex:i] objectForKey:#"nm"];
int tempInt;
NSScanner *scanner= [[NSScanner alloc] init];
scanner = [NSScanner scannerWithString:[[parsedGenres objectAtIndex:i] objectForKey:#"id"]];
[scanner scanInt:&tempInt];
NSNumber *numb = [[NSNumber alloc] init];
numb = [NSNumber numberWithInt:tempInt];
gen.number = [NSNumber numberWithInt:[numb integerValue]];
float k = [parsedGenres count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
[context insertObject:gen];
[gen release];
}
[entityGen release];
[context save:nil];
NSEntityDescription *entityCon = [NSEntityDescription entityForName:#"Country" inManagedObjectContext:context];
NSURL* urlForCoun = [NSURL URLWithString:#"yyy.yyy"];
NSData *countr = [[NSData alloc] initWithContentsOfURL:urlForCoun];
err = nil;
NSArray *parsedCountr = [NSJSONSerialization JSONObjectWithData:countr options:NSJSONReadingMutableContainers error:&err];
if (err)
{
NSLog(#"error is %#", [err localizedDescription]);
}
NSMutableArray* temp = [[NSMutableArray alloc] init];
for (int i =0; i<parsedCountr.count; i++)
{
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
countr.name = [[parsedCountr objectAtIndex:i] objectForKey:#"nm"];
int tempInt;
NSScanner *scanner= [[NSScanner alloc] init];
scanner = [NSScanner scannerWithString:[[parsedCountr objectAtIndex:i] objectForKey:#"id"]];
[scanner scanInt:&tempInt];
NSNumber *numb = [[NSNumber alloc] init];
numb = [NSNumber numberWithInt:tempInt];
countr.number = [NSNumber numberWithInt:[numb integerValue]];
[temp addObject:countr];
float k = [parsedCountr count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
[context insertObject:countr];
[countr release];
}
[context save:nil];
If my app doesn't crash, yes, it happens not by every launch. It crashes on:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
Please help! And sorry for my terrible English.
Update:
On:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
Thread 7: EXC_BAD_ACCESS (code=1, address=0x3f800008)
Other error is exc_bad_access too. But with code=2 and on other thread.
Update 2:
I enabled zombies mode in scheme of my debug. Nothing happened.
Update 3:
I think I have problems with memory.
GuardMalloc: Failed to VM allocate 4128 bytes
GuardMalloc: Explicitly trapping into debugger!!!
You can't pass nil as managedObjectContext parameter to initWithEntity:insertIntoManagedObjectContext: method. Try changing this:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
to this
// pass managed object context parameter
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:context];
Based on the documentation and my experience you can pass nil as managedObjectContext.
I was also getting an EXC_BAD_ACCESS and it came that the reason was that I was not retaining the managed object model(I was only creating a model to get the entity description and then it was released).
In particular, this is what I was doing:
In a test class, in the setUp method:
- (void)setUp
{
[super setUp];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSURL *modelURL = [bundle URLForResource:#"TestDatamodel" withExtension:#"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
STAssertNotNil(model, nil);
_entity = [[model entitiesByName] objectForKey:NSStringFromClass([MyEntity class])];
STAssertNotNil(_entity, nil);
// ...
}
Then in a test method I was creating a managed object without a context like this:
NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:_entity insertIntoManagedObjectContext:nil];
And I was getting EXC_BAD_ACCESS here.
The solution was to add an ivar to the test class to keep a reference to the managed object model.

An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext?

I'm getting this error while trying to use Core Data:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext'
I traced the error back to this in my modal view controller which contains the Table View:
- (void)setupFetchedResultsController
{
NSString *entityName = #"Location";
NSLog(#"Setting up a Fetched Results Controller for the Entity named %#", entityName);
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
// ERROR OCCURS IN THE LINE BELOW vvv
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
[self performFetch];
}
This is what I have in my AppDelegate:
- (void)setupFetchedResultsController
{
NSString *entityName = #"Location";
NSLog(#"Setting up a Fetched Results Controller for the Entity named %#", entityName);
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
[self.fetchedResultsController performFetch:nil];
}
I get no errors there, and here's more of the App Delegate:
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil)
{
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
// Using abort() right now just for development
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:#"Model" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Forecaster.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;
}
#pragma mark - Application's Documents directory
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
and in my Model.xcdatamodeid:
Any help would be great! Thanks!
Here is the Method:
- (void)setupFetchedResultsController
{
NSManagedObjectContext *moc = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:#"Location" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
else
{
// your data is in array
}
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"FailedBankInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (FailedBankInfo *info in fetchedObjects) {
NSLog(#"Name: %#", info.name);
FailedBankDetails *details = info.details;
NSLog(#"Zip: %#", details.zip);
}

Core Data not persisting in iOS 5

V. iOS 5
I have my Model2.xcdatamodelId containg 2 Entities. My Model is named 2, because I already have a Singleton named Model for some managing.
So from that, I have Model2.h and Model2.m.
My Problem : The first time, my Model2 is initialise, I put in some default data, then I commit. Works good, it says that my Model2 has been saved correctly. After what I am reading my data, data are shown from the database.. so it is successfuly in the database. BUT.. when closing and killing my app, my app seems to have lost all data.. and start over again with creating default data cause it is empty...
TIP: I'm thinking my problem could be about the initialize.. whithin those lines:
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSURL * storeUrl = [NSURL fileURLWithPath: [basePath stringByAppendingPathComponent: #"ProjectXYZ.db"]];
Since ProjectXYZ.db doesn't exist, it should create it?.. that's the part where I'm getting lost.. but it seems to worked on another project I've worked on... :S
Here's my Model2.h
#import <CoreData/CoreData.h>
#import "Photos_Trophies.h"
#import "Trophies.h"
#interface Model2 : NSObject
// High-level methods.
+ (void) commit;
...
// Object Retrieval
+ (NSArray*) trophies;
...
// Object Creation
+ (id) trophiesWithTitle:(NSString *)title;
#end
And my Model2.m
#import "Model2.h"
#import <UIKit/UIKit.h>
static NSManagedObjectContext * ctx;
#implementation Model2
+ (void) initialize {
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSURL * storeUrl = [NSURL fileURLWithPath: [basePath stringByAppendingPathComponent: #"ProjectXYZ.db"]];
NSError * error = nil;
ctx = [[NSManagedObjectContext alloc] init];
ctx.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
ctx.undoManager = [[NSUndoManager alloc] init];
if (![ctx.persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
NSLog(#"%#", error);
}
//TEMPORARY... these are default trophies for example
if ([[Model2 trophies] count] == 0) {
[self trophiesWithTitle:#"Saved Trophy Test 1"];
[self trophiesWithTitle:#"Saved Trophy Test 2"];
[self trophiesWithTitle:#"Saved Trophy Test 3"];
[self commit];
}
}
+ (void) commit {
NSError* error = nil;
if (![ctx save:&error]) {
NSLog(#"ERREUR DANS COMMIT: %#", error.localizedDescription);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors && [detailedErrors count] > 0) {
for(NSError* detailedError in detailedErrors)
NSLog(#"DetailedError: %#", [detailedError userInfo]);
} else
NSLog(#"%#", [error userInfo]);
} else
NSLog(#"Model2 SAVED");
}
+ (NSArray*) trophies {
NSFetchRequest* req = [[NSFetchRequest alloc] init];
req.entity = [NSEntityDescription entityForName:#"Trophies" inManagedObjectContext:ctx];
req.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"trophies_title" ascending:YES]];
NSError* error = nil;
NSArray* objects = [ctx executeFetchRequest:req error:&error];
return objects;
}
+ (id) trophiesWithTitle:(NSString *)title {
Trophies * trophies = [NSEntityDescription insertNewObjectForEntityForName:#"Trophies" inManagedObjectContext:ctx];
trophies.trophies_title = title;
return trophies;
}
Your problem is this: NSInMemoryStoreType You need to use a persistent backing store.
Do something like this:
NSURL *storeUrl = [NSURL fileURLWithPath:[self persistentStorePath]];
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]) {
/*
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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
Typical reasons for an error here include:
* The persistent store is not accessible
* The schema for the persistent store is incompatible with current managed object model
Check the error message to determine what the actual problem was.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
NSAssert(error == nil, #"error creating persistentStoreCoordinator");
}