iOS Core Data Persistance After restarting app - core-data

With Core Data, I am able to save and fetch objects in memory; however, when I restart my app (in the simulator) and fetch the results, the object is fetched but all the attributes are nil. I have included all protocol methods in my appdelegate and having initialized my managedObjectContext as such:
managedObjectContext = [self managedObjectContext];
in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Here is what I am getting in the logs...
Correct:
Fetching results log (app not restarted) --> Name: new entry!!!!
Incorrect:
Fetching results log (app restarted) --> Name: (null)
-But, object still exists in persistantStore
--
//Save entry
Entry *entry = (Entry *)[NSEntityDescription insertNewObjectForEntityForName:#"Entries" inManagedObjectContext:managedObjectContext];
[entry setTitle:#"new entry!!!!"];
NSError *error;
if(![managedObjectContext save:&error]){
NSLog(#"SAVE ERROR!!!");
}
//Fetch entry
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Entries" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *info in fetchedObjects) {
NSLog(#"Name: %#", [info valueForKey:#"title"]);
}

Are you sure your Entry class realizes the title property using #dynamic and not #synthetize?

Related

iOS Core Data error when updating

I want to update a field in a table. However when I save after fetching and modifying the field, error 1570 is thrown. [Mandatory value is nil].
MyAppDelegate *appdelegate = DELEGATE;
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyTable" inManagedObjectContext:context];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(myAttribute_id = %#)",myAttribute.attribute_id];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
for (myAttribute *obj in results) {
NSLog(#"myAttribute_id : %#",myAttribute.attribute_id);
[obj setValue:myAttribute.attribute2_id forKey:#"attribute2_id"];
[context save:&error];
NSLog(#"save error : %#",error);
}
Here I get an error. Whereas all mandatory fields are already set.

Core Data Fetch Save relationship while inserting entity (simultaneously)

First question here and I've tried a bunch of stuff and can't figure it out.
Core Data with 2 entities with to-many relationship both ways
A<<---->>B
A entity has name as an attribute, and a relationship Bs
First Controller lists all A entities and i have a second controller to add A entities and I want to have it save a default B in its relationship.
In the prepare for segue I have this code:
if ([[segue identifier] isEqualToString:#"addAEntitySegue"]) {
AddAEntityViewController *addAEntityViewController = [segue destinationViewController];
addAEntityViewController.delegate = self;
addAEntityViewController.managedObjectContext = self.managedObjectContext;
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.addingManagedObjectContext = addingContext;
[addingManagedObjectContext setPersistentStoreCoordinator:[[fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
addAEntityViewController.A = [NSEntityDescription insertNewObjectForEntityForName:#"A" inManagedObjectContext:addingContext];
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:addAEntityViewController
action:#selector(save:)];
addAEntityViewController.navigationItem.rightBarButtonItem = saveButton;
}
In addAEntityViewController i have this to save
-(IBAction)save:(id)sender
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"B" inManagedObjectContext:self.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#",[defaults objectForKey:#"BDefault"]];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
//Set the batch size to a suitable number
[fetchRequest setFetchBatchSize:20];
NSError *error;
self.A.name = textFieldVal;
[self.A addBObject:[[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] objectAtIndex:0]];
NSLog(#"A = %#", self.A.Bs);
[self.delegate addAEntityViewController:self didFinishWithSave:YES];
}
In the addAEntityViewController everything saves correctly even the NSLog(#"A = %#", self.A.Bs); statement shows the B. But when the delegate saves in the First Controller (AEntityViewController) it only saves the A.name but not the relationship A.Bs, I can't figure out what's wrong.
Here's the delegate method:
-(void) addAEntityViewController:self didFinishWithSave:YES{
if (save) {
NSLog(#"saveworkouts");
NSError *error;
if (![addingManagedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
// release the adding managed object context
self.addingManagedObjectContext = nil;
}
Like I said it saves the A entity but not the relationship to B even though the relationship to B saved correctly in the addAEntityViewController (the second View). An NSLOg of A.Bs is null.
First I believe that this line:
addAEntityViewController = self.managedObjectContext;
should be:
addAEntityViewController.managedObjectContext = self.managedObjectContext;
but that would also be wrong.
it should be getting the addingContext you created afterwards:
addAEntityViewController.managedObjectContext = addingContext;
I'm a bit surprised that your app didn't crash, as you are mixing managed objects from 2 different contexts.

Core Data - One to Many relationship with object(one) and UIImages(many), storing and fetching

I aim to build a app with the object of:
- Request(contains an unique id, customer name, phone, email, a brief summary of request info, a list of images(store in NSMutable Array)
My Core data contains:
Request
Image
For my request object, I have:
#import <Foundation/Foundation.h>
#interface BAPRequest : NSObject
#property (nonatomic, retain) NSString *requestID;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *email;
#property (nonatomic, retain) NSString *phone;
#property (nonatomic, retain) NSString *detail;
#property (nonatomic, retain) NSMutableArray *images;
#property (nonatomic, retain) NSDate *requestDate;
#property (nonatomic) BOOL isSent;
- (void)fetchImages;
#end
And the .m File:
#import "BAPAppDelegate.h"
#import "BAPRequest.h"
#implementation BAPRequest
#synthesize name, email, phone, detail;
#synthesize images;
#synthesize requestDate;
#synthesize isSent;
#synthesize requestID;
- (id)init{
self = [super init];
if(self != nil){
self.isSent = false;
self.requestID = [[NSProcessInfo processInfo] globallyUniqueString];
self.images = [[NSMutableArray alloc] init];
}
return self;
}
- (void)fetchImages{
//get delegation
BAPAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
//init request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
//load the entity description
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Image"
inManagedObjectContext:context];
//set the request query
[fetchRequest setEntity:entityDescription];
//set predicate to request to ask select specific entity with the matching line num
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(requestId == %#)", self.requestID];
[fetchRequest setPredicate:pred];
//exec the command to find the object(table) from core database
NSArray * imageList = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *imageObject in imageList){
[self.images addObject: [UIImage imageWithData:[imageObject valueForKey:#"content"]]];
}
}
#end
To fetch all the requests, I also do:
- (void)removeRequest:(BAPRequest*)request{
//get delegation
BAPAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
//init request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
//load the entity description
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Request"
inManagedObjectContext:context];
//set the request query
[fetchRequest setEntity:entityDescription];
//set predicate to request to ask select specific entity with the matching line num
NSLog(#"request id is %#", request.requestID);
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(requestId LIKE %#)", request.requestID];
[fetchRequest setPredicate:pred];
//exec the command to find the object(table) from core database
NSArray *objects = [context executeFetchRequest:fetchRequest error:&error];
//if this object doesn't exist in the database, it must be something wrong
if (objects == nil) {
NSLog(#"There was an error !");
NSLog(#"Error Info: %#", error);
}
//if object exist in database, take the first search object, and deletes it
if ([objects count] > 0){
NSManagedObject *theRequest = [objects objectAtIndex:0];
[context deleteObject:theRequest];
}
[context save:&error];
/*
//delete existing images relates to this request first
entityDescription = [NSEntityDescription entityForName:#"Image"
inManagedObjectContext:context];
pred = [NSPredicate predicateWithFormat:#"(self.request == %#)", request];
[fetchRequest setPredicate:pred];
NSArray * imageList = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *removeImageObject in imageList){
[context deleteObject:removeImageObject];
}
*/
}
#pragma mark - Convert Core Data Object to Request Object
#pragma mark - Core Data Methods
- (NSMutableArray *)getRequests{
//get app delegate
BAPAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
//get object context that's created for us
NSManagedObjectContext *context = [appDelegate managedObjectContext];
//define the entities we want load to description
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Request"
inManagedObjectContext:context];
//init request and set search query to the request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entityDescription];
NSError *error;
//get objects(table) though request
NSArray *objects = [context executeFetchRequest:fetchRequest error:&error];
if (objects == nil){
NSLog(#"There was an error !");
//error handling there
NSLog(#"Error Info: %#", error);
}
NSMutableArray *requests = [[NSMutableArray alloc] init];
for (NSManagedObject *requestObj in objects){
BAPRequest *request = [[BAPRequest alloc] init];
request.requestID = [requestObj valueForKey:#"requestId"];
request.name = [requestObj valueForKey:#"name"];
request.email = [requestObj valueForKey:#"email"];
request.phone = [requestObj valueForKey:#"phone"];
request.detail = [requestObj valueForKey:#"detail"];
request.requestDate = [requestObj valueForKey:#"requestDate"];
request.isSent = [[requestObj valueForKey:#"isSent"] boolValue];
[request fetchImages];
[requests addObject: requestObj];
}
return requests; //return the requests
}
- (void)saveRequest:(BAPRequest *)request{
request.requestDate = [NSDate date];
//get delegation
BAPAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
BAPRequest *theRequest = [NSEntityDescription insertNewObjectForEntityForName:#"Request"
inManagedObjectContext:context];
//set the request obejct basics
[theRequest setValue:request.requestID forKey:#"requestId"];
[theRequest setValue:request.name forKey:#"name"];
[theRequest setValue:request.email forKey:#"email"];
[theRequest setValue:request.phone forKey:#"phone"];
[theRequest setValue:request.detail forKey:#"detail"];
[theRequest setValue:request.requestDate forKey:#"requestDate"];
[theRequest setValue:[NSNumber numberWithBool:request.isSent ] forKey:#"isSent"];
//also save its requests
for (UIImage *img in request.images) {
//init image object
UIImage *newImage=[NSEntityDescription insertNewObjectForEntityForName:#"Image" inManagedObjectContext:context];
[newImage setValue:request.requestID forKey:#"requestId"];
[newImage setValue:UIImagePNGRepresentation(img) forKey:#"content"];
}
[context save:&error]; //save the object
}
#end
My Issue is:
I guess it just doesn't fetch the images at all. Even they fetched the images in the getRequests method, when I try to pass the request to somewhere else, it still get lots issues:
boolean not loading properly
images are nil(even it was loaded when fetch)
and the reason is(I can be wrong) that when I store these request objects(BAPRequest*) into a NSArray and pass it to a table view, when I load them from array (e.g [myArray objectAtIndex:0]), they are still NSManagedObject. I tried to give a class name in the core data entity option to make the Request(Core Data) Object Class of BAPRequest, but it keeps saying I have to subclass NSManagedObject, where subclassing NSManagedObject is not possible:
I can't do:
BAPRequest: NSManagedObject
XCode doesn't likes it.
Look at mogenerator. Here's a tutorial on how to use it: http://raptureinvenice.com/getting-started-with-mogenerator/ . It will save you a lot of trouble.

NSFetchedResultsController with NSPredicate not updating

I fetch data from a Core Data-base and present them in a UITableView. I use a NSFetchedResultController to fetch the data. I want the user to be able to search in the database, and to do that I use a NSPredicate.
The data is presented in the UITableView and everything works well until I set the NSPredicate to the NSFetchedResultController.
I use this in the ViewDidLoad method:
self.fetchedResultsController = nil;
fetchedResultsController_ = nil;
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1);
}
and when the user has entered a text from the UITextField, that text will go to the new NSPredicate.
This is done when the search starts:
NSPredicate *pred = nil;
pred = [NSPredicate predicateWithFormat:#"(Designation BEGINSWITH '22')"];
[fetchedResultsController_.fetchRequest setPredicate:pred];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1);
}
[tView reloadData];
Right now I use #"(Designation BEGINSWITH '22')" for testing only.
This is my NSFetchedResultsController:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController_ != nil) {
return fetchedResultsController_;
}
/*
Set up the fetched results controller.
*/
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Product" inManagedObjectContext:importContext];//self.managedObjectContext
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Designation" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:importContext sectionNameKeyPath:nil cacheName:#"Root"]; //self.managedObjectContext
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController_;
}
The problem is that the fetched data stays the same, no matter how or if I set a predicate. If I would set a predicate in the viewDidLoad it would work, but then I wouldn't be able to get new results if I'd tried that again. I use an "importContext" for a batch-import of my CoreData.
Any ideas?
Thanks in advance!
UPDATE:
Ok, here is what I found out. I have an importContext where I make a batch-import. And for the fetchController I use self.managedObjectContext. That's why it doesn't work, so I have to make self.managedObjectContext have the same stuff as my importContext somehow...
You're using a cache (#"Root")… Try setting it to nil, this could prevent crashes. You should not cache FetchedResultsControllers meant to be Predicated.
Even better than setting the cache to nil is giving it a unique name. After posting this question
iPhone - Cache name for NSFetchedResultsController
I added a function to generate UUIDs as my cache names.

Coredata for getting all the values of a field

I have an entity ("Settings") and I want to get all the values in just one field ("Status").I am using coredata. Can anyone help me, please?
Declare this in .h file:
NSMutableArray *eventArray;
and in .m file
- (void)fetchRecords {
// Setup the fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Define our table/entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Settings" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Status" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setEntity:entity];
[fetchRequest setEntity:entity];
NSError *error;
// Get array of results.
NSMutableArray *theResults = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
if (!theResults) {
// Handle the error.
// This is a serious error and should advise the user to restart the application
}
// Grab unique neighborhoods through NSSet.
NSSet *uniqueElements = [NSSet setWithArray:[theResults valueForKey:#"Status"]];
// Dump NSSet uniques into new array.
NSMutableArray *sortedResults = [[NSMutableArray alloc] initWithArray:[uniqueElements allObjects]];
for(int i = 0; i < [sortedResults count];i++)
{
NSLog(#"%d. %#", i+1, [sortedResults objectAtIndex:i]);
}
// Save our fetched data to an array
[self setEventArray: sortedResults];
}
At first, u can get Array of values:
NSFetchRequest *requestSettings = [[NSFetchRequest alloc] init];
[requestCodesList setEntity:[NSEntityDescription entityForName:#"Setting" inManagedObjectContext:managedObjectContext]];
NSArray *setting = [managedObjectContext executeFetchRequest:requestCodesList error:&error];
if (error) NSLog(#"Failed to executeFetchRequest to data store: %#", [error localizedDescription]);
Next, u transfer u array in NSString:
ComponentsJoinedByString: Constructs
and returns an NSString object that is
the result of interposing a given
separator between the elements of the
array.
(NSString *)componentsJoinedByString:(NSString *)separator
code is:
NSString *settingChanged = [setting componentsJoinedByString:#","];
And after u can using this anywhere in u UI (binding, setStringValue e.t.c)

Resources