I am newbie in Core Data. I put all model requirements (in respect of MVC) in a class of NSFetchedResultsController as below:
Header File :
#import <CoreData/CoreData.h>
#interface GeneralModel : NSFetchedResultsController
#property (nonatomic, strong) NSManagedObjectContext *context;
#property (nonatomic, strong) NSManagedObjectModel *model;
- (NSString *)storagePath;
- (void)removeStorage;
- (void)truncateAllEntity;
- (void)truncateEntity:(NSString *)entityName;
- (void)addGroups:(NSDictionary *)insertData;
- (NSArray *)getEntity:(NSString *)entityName sortBy:(NSString *)sortAttribute;
- (id)getMaxValue:(NSString *)entityName forProperty:(NSString *)propertyName;
- (NSArray *)getEntity:(NSString *)entityName predicateBy:(NSPredicate *)predicate sortBy:( NSString * )sortAttribute;
#end
Main File:
#import "GeneralModel.h"
#import "GeneralHelper.h"
#implementation GeneralModel
- (instancetype)init
{
self = [super init];
if (self) {
// Read in Model.xcdatamodeld
_model = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *psc =
[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_model];
// Where does the SQLite file go?
NSString *path = self.storagePath;
NSURL *storeURL = [NSURL fileURLWithPath:path];
NSError *error = nil;
if (![psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:&error]) {
#throw [NSException exceptionWithName:#"OpenFailure"
reason:[error localizedDescription]
userInfo:nil];
}
// Create the managed object context
_context = [[NSManagedObjectContext alloc] init];
_context.persistentStoreCoordinator = psc;
}
return self;
}
- (NSString *)storagePath
{
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
// Get one and only document directory from that list
NSString *documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingPathComponent:#"model.sqlite"];
}
- (void)removeStorage {
// NSError *error2;
// NSString *storagePath = [self storagePath];
//
// NSDictionary *options = #{NSPersistentStoreUbiquitousContentNameKey: #"model"};
// bool removeResult = [NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:[NSURL URLWithString:storagePath] options:options error:&error2];
// if (removeResult == NO) {
// NSLog(#"Could not remove Storage. Reason: %#", error2.localizedFailureReason);
// }
NSPersistentStore *store = [self.context.persistentStoreCoordinator.persistentStores lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
BOOL isRemovePersistentStore = [self.context.persistentStoreCoordinator removePersistentStore:store error:&error];
if (isRemovePersistentStore == NO) {
NSLog(#"NO RemovePersistentStore. Reason: %#", error.localizedFailureReason);
}
BOOL isRemoveItemAtURL = [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
if (isRemoveItemAtURL == NO) {
NSLog(#"NO RemoveItemAtURL. Reason: %#", error.localizedFailureReason);
}
}
- (void)truncateAllEntity {
NSArray *entities = self.model.entities;
for (NSEntityDescription *entityDescription in entities) {
[self truncateEntity:entityDescription.name];
}
}
- (void)truncateEntity:(NSString *)entityName {
// delete all database
if (IOS_VERSION >= 9) {
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:entityName];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
NSError *deleteError = nil;
[self.context.persistentStoreCoordinator executeRequest:delete withContext:self.context error:&deleteError];
} else {
NSFetchRequest *allItems = [[NSFetchRequest alloc] init];
[allItems setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:self.context]];
[allItems setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError *error = nil;
NSArray *items = [self.context executeFetchRequest:allItems error:&error];
//error handling goes here
for (NSManagedObject *item in items) {
[self.context deleteObject:item];
}
NSError *saveError = nil;
[self.context save:&saveError];
//more error handling here
}
[self.context rollback];
}
- (void)addGroups:(NSDictionary *)insertData {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
for (NSDictionary *response in insertData) {
NSManagedObject *existingGroup = [self getEntity:#"Group" AtValue:response[#"groupId"] forProperty:#"group_id" ];
if (existingGroup) {
NSLog(#"existingGroup");
continue;
}
// for (int i; i<=20; i++) {
// set bullet
NSManagedObject *object_bullet = [NSEntityDescription insertNewObjectForEntityForName:#"Group_bullet"
inManagedObjectContext:self.context];
NSData *bulletData = [[NSData alloc] initWithBase64EncodedString:response[#"bullet"] options:NSDataBase64DecodingIgnoreUnknownCharacters];
[object_bullet setValue:bulletData forKey:#"bullet"];
[object_bullet setValue:response[#"groupId"] forKey:#"group_id"];
// set group
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:#"Group"
inManagedObjectContext:self.context];
[object setValue:object_bullet forKey:#"relatedBullet"];
// NSDate *createDate = [dateFormatter dateFromString:response[#"createDate"]];
// [object setValue:createDate forKey:#"group_created_date"];
NSNumber *createDate = response[#"createDate"];
[object setValue:[NSDate dateWithTimeIntervalSince1970:[createDate doubleValue]] forKey:#"group_created_date"];
[object setValue:response[#"groupId"] forKey:#"group_id"];
[object setValue:[GeneralHelper getInteger:response[#"memberNumber"]] forKey:#"group_members_count"];
[object setValue:response[#"name"] forKey:#"group_name"];
[object setValue:[GeneralHelper getInteger:response[#"privacy"]] forKey:#"group_privacy"];
[object setValue:#1 forKey:#"group_status"];
[object setValue:response[#"imageName"] forKey:#"image_name"];
[object setValue:response[#"lastMessageId"] forKey:#"last_message_id"];
[object setValue:response[#"lastMessageText"] forKey:#"last_message_text"];
//
// NSDate *lastMessageDate = [dateFormatter dateFromString:response[#"lastMessageDate"]];
// [object setValue:lastMessageDate forKey:#"last_time"];
NSNumber *lastMessageDate = response[#"lastMessageDate"];
[object setValue:[NSDate dateWithTimeIntervalSince1970:[lastMessageDate doubleValue]] forKey:#"last_time"];
[object setValue:response[#"machineId"] forKey:#"machine_id"];
NSNumber *timestamp = response[#"timestamp"];
[object setValue:[NSDate dateWithTimeIntervalSince1970:[timestamp doubleValue]] forKey:#"timestamp"];
[object setValue:[GeneralHelper getInteger:response[#"unreadCount"]] forKey:#"unread_count"];
// }
}
NSError *errorInsert;
if (![self.context save:&errorInsert]) {
NSLog(#"Failed to save - error: %#", [errorInsert localizedDescription]);
}
[self.context rollback];
}
- (id)getMaxValue:(NSString *)entityName forProperty:(NSString *)propertyName {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:entityName];
fetchRequest.fetchLimit = 1;
fetchRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:propertyName ascending:NO]];
NSError *error = nil;
id maxValue = [self.context executeFetchRequest:fetchRequest error:&error].firstObject;
if (maxValue == nil) {
maxValue = #{propertyName : #0};
}
[self.context rollback];
return [maxValue valueForKey:propertyName];
}
- (id)getEntity:(NSString *)entityName AtValue:(NSString *)indexValue forProperty:(NSString *)propertyName {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.context];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K == %#", propertyName, indexValue];
// NSLog(#"predicate: %#", predicate);
[request setEntity:entity];
[request setPredicate:predicate];
[request setFetchLimit:1];
NSError *error;
NSArray *results = [self.context executeFetchRequest:request error:&error];
NSManagedObject *object = [results firstObject];
// if (object) {
// // there is at least one object matching you predicate
// } else {
// // there is no object matching your predicate in the moc
// }
// NSLog(#"results member %#", results);
// [self.context rollback];
return object;
}
Then I use this general model in my UITableViewController.
Is there any better way to do this? Or my implementation is buggy and useless?
It think this is a nice approach, but it has some drawbacks.
An NSFetchedResultsController is responsible, as the name implies for controlling results that were fetched. If you add functionality like deleting and modifying things, you are making an object with too many responsibilities.
Imagine there is one viewController showing results in a tableview. It would only need the fetchedresultscontroller functionality, nothing more. If by tapping on a cell you go into a new view controller where edits are possible, you don't need a fetchedresultscontroller: you need a managedObject to edit. This editViewController could use a child context of the tableViewController so that on cancel, all edits are discarded by simply discarding the child context.
I would suggest to no subclass the NSFetchedResultsController, but instead implement a subclass of NSObject that you initialize with an NSNMagedObjectContext that can do the things that apply to the entire context. Like adding groups, removing all data etc.
Then use composition: this NSObject subclass can be a property of a viewController so the viewCOntroller has a way to do those things without having this operation being specific to this viewController.
In general, instead of subclassing, consider composition first. This is because transforming a small components of a composed object to an object that is a certain subclass is usually easier then the other way around.
Feel free to disagree :), but this is what I've learned from experience of working with many people for a long time on a very large codebase.
Related
i am new to core data..
I know how to store and item.
- (void)dbSave:(NSString *)uri withContent:(NSDictionary *)content withExpiry:(double)date {
Cache *cache = [self dbLoad:uri];
if (cache == nil) {
cache = [NSEntityDescription insertNewObjectForEntityForName:#"Cache" inManagedObjectContext:[self managedObjectContext]];
}
double time = (double) [[NSDate date] timeIntervalSince1970] + date;
[cache setLocal:uri];
[cache setTime:#(time)];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:content forKey:#"data"];
[archiver finishEncoding];
[cache setData:data];
NSError *error;
if (![[self managedObjectContext] save:&error]) {
}
}
But i am stuck with creating a method to clear this core data data base.. Does anyone know how?
NSManagedObjectContext *managedObjectContext=[appDelegate managedObjectContext];
NSFetchRequest *fetchRequest=[NSFetchRequest fetchRequestWithEntityName:#"entity"];
NSArray* currentRecord = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
if (currentRecord.count)
{
for (NSManagedObject *obj in currentRecord)
{
[managedObjectContext deleteObject:obj];
}
NSError * error = nil;
if (![managedObjectContext save:&error])
NSLog(#"Can't save ! %# %#",error,[error localizedDescription]);
else
NSLog(#"Data deleted");
}
use this
NSManagedObjectContext *managedContext = [[APP_DELEGATE dbManagerObj] newPrivateContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Cache"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isUserData = %#",[NSNumber numberWithBool:true]];
[fetchRequest setPredicate:predicate];
if (IS_IOS9_ANDABOVE) {
NSBatchDeleteRequest *batchDeleteRequest = [[NSBatchDeleteRequest alloc]initWithFetchRequest:fetchRequest];
[[[APP_DELEGATE dbManagerObj]persistentStoreCoordinator]executeRequest:batchDeleteRequest withContext:managedContext error:nil];
}
else
{
NSArray *userRelatedDay = [managedContext executeFetchRequest:fetchRequest error:nil];
for (NSManagedObject *object in userRelatedDay) {
[managedContext deleteObject:object];
}
}
I am developing iOS app, which fetch data from Web Services and save it to local database and uses it various views as needed. The data is fetch from Web Service and save to database correctly. But while accessing data from NSManagedObject it show FAULT and the consequent NSDictionary shows null Values
The code follows:-
-(void)SaveData:(NSInteger)menuId categoryID:(NSInteger)catID caption:(NSString *)title parentID:(NSInteger)parentID
{
BBAppDelegate *appDelegate = [[BBAppDelegate alloc]init];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *userobj = [NSEntityDescription insertNewObjectForEntityForName:tableName
inManagedObjectContext:context];
[userobj setValue:[NSNumber numberWithInt:menuId] forKey:#"id"];
[userobj setValue:[NSNumber numberWithInt:catID] forKey:#"catid"];
[userobj setValue:[NSNumber numberWithInt:parentID] forKey:#"parentid"];
[userobj setValue:title forKey:#"caption"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
NSLog(#"app dir: %#",[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);
}
-(NSArray *)fetchedData{
BBAppDelegate *appdelegate = [[BBAppDelegate alloc]init];
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *readData = [[NSFetchRequest alloc] init];
[readData setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription
entityForName:tableName inManagedObjectContext:context];
[readData setEntity:entity];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:readData error:&error];
// for (Test *test in array)
// {
// NSLog(#"Test: %# ", test.text);
// }
NSLog(#"%#",results);
return results;
}
-(void)removeData{
BBAppDelegate *appdelegate = [[BBAppDelegate alloc]init];
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *delData = [[NSFetchRequest alloc]init];
[delData setEntity:[NSEntityDescription entityForName:tableName inManagedObjectContext:context]];
[delData setIncludesPropertyValues:NO];
NSError *error = nil;
NSArray *result = [context executeFetchRequest:delData error:&error];
for (NSManagedObject *value in result) {
[context deleteObject:value];
}
NSError *saveError = nil;
[context save:&saveError];
}
-(void)table:(NSString *)nameTable{
tableName =nameTable;
}
- (instancetype)initWithTableName:(NSString *)tablename
{
[self table:tablename];
return self;
}
-(NSMutableArray *)buldMenu{
NSArray *array = [self fetchedData];
return [self getmenus:0 arr:array];
}
-(NSMutableArray *)getmenus:(NSInteger)parentID arr: (NSArray *)array
{
NSMutableArray *aray = [[NSMutableArray alloc]init];
for (NSManagedObject *dic in array) {
if (dic.faultingState != 0) {
NSLog(#"%lu",(unsigned long)dic.faultingState);
//return nil;
}
NSArray *keys = [[[dic entity] attributesByName] allKeys];
NSLog(#"%#",keys);
NSDictionary *dict = [dic dictionaryWithValuesForKeys:keys];
NSLog(#"%#",dic);
NSLog(#"%#",dict);
NSInteger pID = [[dict objectForKey:#"parentid"]integerValue];
if (pID == parentID) {
BBMenuEntry *entryMenu = [[BBMenuEntry alloc]init];
entryMenu.menuID = [[dict objectForKey:#"id"]integerValue];
entryMenu.catID = [[dict objectForKey:#"catid"]integerValue];
entryMenu.caption = [dict objectForKey:#"caption"];
entryMenu.subMenus = [self getmenus:entryMenu.menuID arr:array];
[aray addObject:entryMenu];
}
}
return aray;
}
I am using storyboard and and coredata in my app. In the home screen i want to list all my audio file details and in a button click i want to navigate to another screen and record a new file and save that file in database. When pressing back button i reached to home screen and i want to display the saved audio files in a tableview. Table row count is showing correctly. But the audio details are not correct. But when i stop and rebuild the app it is showing correctly. I wrote the code for reloading the tableview in viewWillApper.
- (void)viewWillAppear:(BOOL)animated
{
[tableview reloadData];
[self loadFiles];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"AudioDetails" inManagedObjectContext:managedObjectContext]];
[request setIncludesSubentities:NO]; NSError *err;
NSUInteger count = [managedObjectContext countForFetchRequest:request error:&err];
return count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"AudioCell";
AudioCell *cell = (AudioCell *)[tableViewdequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (AudioCell *)[nibArray objectAtIndex:0];
[cell configurePlayerButton];
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"AudioDetails" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *info in fetchedObjects) {
if(audionames == nil)
audionames = [[NSMutableArray alloc] init];
[audionames addObject:[info valueForKey:#"audioName"]];
//NSManagedObject *details = [info valueForKey:#"details"];
//NSLog(#"Zip: %#", [details valueForKey:#"zip"]);
}
cell.titleLabel.text = [audionames objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)SaveRecordingBtnClicked:(id)sender {
NSString *soundFilePath = [[self getDocumentDirectoryPath]
stringByAppendingPathComponent:OrginalAudioFileName];
NSURL *path=[NSURL URLWithString:soundFilePath];
NSError *error = nil;
AVAudioPlayer* avAudioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:path error:&error];
NSManagedObjectContext *context = [self managedObjectContext];
AudioDetails *audioDetails = [NSEntityDescription
insertNewObjectForEntityForName:#"AudioDetails"
inManagedObjectContext:context];
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:soundFilePath error:&error];
NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
NSDate *fileCreationDate = [fileAttributes objectForKey:NSFileCreationDate];
int duration = avAudioPlayer.duration;
[audioDetails setValue:[NSString stringWithFormat:#"%#",OrginalAudioFileName] forKey:#"audioName"];
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
}
I'm creating an object with the following code:
+(Checkin *) newCheckinWithId:(NSString*) checkinID forVenueId:(NSString *)venueId
{
NSManagedObjectContext * context = [[AppDelegate sharedInstance] managedObjectContext];
Checkin *ret = (Checkin *)[NSEntityDescription insertNewObjectForEntityForName:#"Checkin" inManagedObjectContext:context];
ret.checkinID = checkinID;
ret.forVenueID = venueId;
ret.date = [NSDate date];
NSError * error;
if(![context save:&error]) {
NSLog(#"Error saving!!!!!: %#", error.userInfo);
}
return ret;
}
This code works, and I can see the objects in the sqldatabase file on disk (in ~/library/iphone sim/.. whatever it is)
Here is the code I use to create my store + managed object context (I use 1 context for everything) Its basically all from a stack overflow post I found
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil)
{
return _managedObjectModel;
}
//NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Model" withExtension:#"momd"];
//__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
//NSArray *testArray = [[NSBundle mainBundle] URLsForResourcesWithExtension:#"momd"subdirectory:nil];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Model" ofType:#"momd"];
if( !path ) path = [[NSBundle mainBundle] pathForResource:#"Model" ofType:#"mom"];
NSURL *modelURL = [NSURL fileURLWithPath:path];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
//__managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if((_persistentStoreCoordinator != nil)) {
return _persistentStoreCoordinator;
}
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSPersistentStoreCoordinator *psc = _persistentStoreCoordinator;
// Set up iCloud in another thread:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// ** Note: if you adapt this code for your own use, you MUST change this variable:
NSString *iCloudEnabledAppID = #"[MY APP ID]";
// ** Note: if you adapt this code for your own use, you should change this variable:
NSString *dataFileName = #"foursquareaugmentation.sqlite";
// ** Note: For basic usage you shouldn't need to change anything else
NSString *iCloudDataDirectoryName = #"Data.nosync";
NSString *iCloudLogsDirectoryName = #"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloud) {
NSLog(#"iCloud is working");
NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];
NSLog(#"iCloudEnabledAppID = %#",iCloudEnabledAppID);
NSLog(#"dataFileName = %#", dataFileName);
NSLog(#"iCloudDataDirectoryName = %#", iCloudDataDirectoryName);
NSLog(#"iCloudLogsDirectoryName = %#", iCloudLogsDirectoryName);
NSLog(#"iCloud = %#", iCloud);
NSLog(#"iCloudLogsPath = %#", iCloudLogsPath);
if([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
NSError *fileSystemError;
[fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
withIntermediateDirectories:YES
attributes:nil
error:&fileSystemError];
if(fileSystemError != nil) {
NSLog(#"Error creating database directory %#", fileSystemError);
}
}
NSString *iCloudData = [[[iCloud path]
stringByAppendingPathComponent:iCloudDataDirectoryName]
stringByAppendingPathComponent:dataFileName];
NSLog(#"iCloudData = %#", iCloudData);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey];
[options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey];
[psc lock];
NSError *error;
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:[NSURL fileURLWithPath:iCloudData]
options:options
error:&error];
if( error )
{
NSLog(#"Error adding persistent store %#, %#", error, [error userInfo]);
// comment in this line while debugging if get "Can't find model for source store" error in addPersistentStoreWithType.
// it means the sqlite database doesn't match the new model and needs to be created from scratch.
// this happens if you change the xcdatamodel instead of creating a new one under Xcode->Editor->Add Model Version...
// CoreData can only automatically migrate if there is a new model version (it can't migrate if the model simply changes, because it can't see the difference between the two models).
// be sure to back up the database if needed, because all data will be lost.
//[fileManager removeItemAtPath:iCloudData error:&error];
/*// this is another way to verify the hashes for the database's model to make sure they match one of the entries in the momd directory's VersionInfo.plist
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:[NSURL fileURLWithPath:iCloudData] error:&error];
if( !sourceMetadata )
NSLog(#"sourceMetadata is nil");
else
NSLog(#"sourceMetadata is %#", sourceMetadata);*/
}
[psc unlock];
}
else {
NSLog(#"iCloud is NOT working - using a local store");
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[psc lock];
NSError *error;
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:localStore
options:options
error:nil];
if( error )
NSLog(#"Error adding persistent store %#, %#", error, [error userInfo]);
[psc unlock];
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"SomethingChanged" object:self userInfo:nil];
});
});
return _persistentStoreCoordinator;
}
/*
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *) managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return _managedObjectContext;
}
Here is my fetch:
+(NSArray *) checkinsForVenue:(NSString *) venueID
{
NSManagedObjectContext * context = [[AppDelegate sharedInstance] managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Checkin" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = entity;
//NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(forVenueID = %#)", venueID];
//request.predicate = predicate;
NSError *error;
NSArray * ret = [context executeFetchRequest:request error:&error];
if(ret == nil) {
NSLog(#"%#", error.description);
}
return ret;
}
Fetch always returns no objects (the empty array) even though there are things in the database!
I've been working on this problem for quiet a while and am pretty out of ideas so anything appreciated!
Thanks
Try this code to fetch data:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil )
{
return _fetchedResultsController;
}
NSLog(#"Length:: %d",[[_fetchedResultsController mutableCopy] length]);
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"OrderDetails"];
[fetchRequest setIncludesSubentities:YES];
// Sort by Application name
NSSortDescriptor* sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"orderId" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
//Sort by CommandNameloca
NSArray* sortDescriptors = [[NSArray alloc] initWithObjects: sortDescriptor1, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:100];
ordersArr=[[NSMutableArray alloc]initWithArray:sortDescriptors];
NSLog(#"----- ordersArr Count == %d",[ordersArr count]);
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"orderId" cacheName:#"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&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();
}
return _fetchedResultsController;
}
After this method i executed write this line to store data in your app array like this:
NSMutableArray *myArr=[[NSMutableArray alloc]initWithArray:self.fetchedResultsController.fetchedObjects];
I have a number of objects (NSManagedObject Subclass) which 'seem' to be created and saving correctly, however on reloading i can only get null from any of the variables within the objects.
The right number of objects are being saved, but none of the variables.
I've gone through the code several times, and I cant figure out if the problem is on the saving side or the loading side.
Would very much appreciate any thoughts!
Thanks in advance
//Create a route
- (CNSRoute *) createRoute
{
CNSRoute *p = [NSEntityDescription insertNewObjectForEntityForName:#"CNSRoute" inManagedObjectContext:context];
[allRoutes addObject:p];
//NSLog(#"Route: %#", p);
return p;
}
//Load all routes from core data
- (void) loadAllRoutes
{
NSLog(#"All Routes: %#", allRoutes);
if (!allRoutes) {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *e = [[model entitiesByName] objectForKey:#"CNSRoute"];
[request setEntity:e];
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sd]];
NSError *error;
NSArray *result = [context executeFetchRequest:request error:&error];
if (!result) {
[NSException raise:#"Fetch Failed" format:#"Reason: %#", [error localizedDescription]];
}
NSLog(#"LOAD RESULT: %#", result);
for (CNSRoute *route in result) {
NSLog(#"Loading Route... %#", [route name]);
}
allRoutes = [[NSMutableArray alloc] init];
[allRoutes setArray:result];
//NSLog(#"%#", allLocations);
}
}
//Save context
- (BOOL)saveChanges
{
NSError *err = nil;
BOOL successful = [context save:&err];
if (!successful) {
NSLog(#"ERROR SAVING: %#", [err localizedDescription]);
}
return successful;
}
//Save when application enters background
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[CNSTravelController sharedStore] saveChanges];
}