Only Able to Save The First Object - ios

A problem I'm facing right now is that when I try to save objects, Core Data appears to only save the first one.
Code to save objects
- (void)savingResCore {
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
ResultMO *resEntity = [NSEntityDescription insertNewObjectForEntityForName:#"Result" inManagedObjectContext:context];
if(indCheck == 1) {
resEntity.result1 = pena1;
resEntity.resuName1 = penaNam1;
}
if(indCheck == 2) {
resEntity.result2 = pena2;
resEntity.resuName2 = penaNam2;
}
if(indCheck == 3) {
resEntity.result3 = pena3;
resEntity.resuName3 = penaNam3;
}
_seqNameChk = [NSNumber numberWithInt:[_seqNameChk intValue] - 1];
if([_seqNameChk isEqual:#(0)]){
NSError *error = nil;
if (context != nil) {
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
}
Code to fetch objects
- (void)fetchResCore {
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSEntityDescription *descriptor = [NSEntityDescription entityForName:#"Result" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
request.entity = descriptor;
NSError *error;
NSArray *contArr = [context executeFetchRequest:request error:&error];
if(contArr == nil){
NSLog(#"Problems fetching data.");
}
else if(contArr != nil) {
if(contArr.count == 0) {
NSLog(#"No objects saved");
}
else {
NSManagedObject *resu = (NSManagedObject *)[contArr objectAtIndex:0];
NSLog(#"1 - %#", resu);
pena1 = [resu valueForKey:#"result1"];
penaNam1 = [resu valueForKey:#"resuName1"];
NSLog(#"%#", pena1);
pena2 = [resu valueForKey:#"result2"];
penaNam2 = [resu valueForKey:#"resuName2"];
NSLog(#"%#", pena2);
pena3 = [resu valueForKey:#"result3"];
penaNam3 = [resu valueForKey:#"resuName3"];
NSLog(#"%#", pena3);
NSLog(#"2 - %#", resu);
}
}
}
For example, I have a button that increments indCheck by one each time it is pressed and each time it calls up the fetchResCore method. Assume seqNameChk = 2. For the first time, the attributes result1 & resuName1 gets saved successfully. After the button is pressed consecutively, it no longer saves data. Hence, attributes result2, resuName2, result3 & resuName3 does not contain data when retrieved at the fetchResCore method.
Result printed in the console for resu
resuName1 = "(\n Alan\n)";
resuName2 = nil;
resuName3 = nil;
result1 = "(\n 100\n)";
result2 = nil;
result3 = nil;
Result printed in the console for contArr
result1 = \"(\\n 100\\n)\";\n result2 = nil;\n result3 = nil;\n
resuName1 = \"(\\n Alan\\n)\";\n resuName2 = nil;\n resuName3 = nil;\n

As Jon Rose had pointed out,
I would assume that they are all in the array contArr but you are only looking at the first one: NSManagedObject *resu = (NSManagedObject *)[contArr objectAtIndex:0];
I printed out contArr.count and it resulted in a 3. I've also printed out the contents of the array by using a for loop and again, 3 elements which were populated, was displayed.
To solve the problem, I had to rectify [contArr objectAtIndex:0] as it only displayed the first element in the array.
In the fetchResCore method
for(int i = 0; i < contArr.count; i++){
NSManagedObject *resu = (NSManagedObject *)[contArr objectAtIndex:i];
NSLog(#"1 - %#", resu);
if(pena1.count == 0 && penaNam1.count == 0){
pena1 = [resu valueForKey:#"result1"];
penaNam1 = [resu valueForKey:#"resuName1"];
NSLog(#"%#", pena1);
}
if(pena2.count == 0 && penaNam2.count == 0){
pena2 = [resu valueForKey:#"result2"];
penaNam2 = [resu valueForKey:#"resuName2"];
NSLog(#"%#", pena2);
}
if(pena3.count == 0 && penaNam3.count == 0){
pena3 = [resu valueForKey:#"result3"];
penaNam3 = [resu valueForKey:#"resuName3"];
NSLog(#"%#", pena3);
}
}
Thanks again, Jon Rose for pointing out a simple mistake that took me days to figure out.

Related

Inconsistency in Saving/Fetching Data in Core Data

My first post here, getting straight to the point.
I'm facing a problem and I'm not sure whether is with saving of data or fetching it.
Here are my codes where I tried to save the data in my Entity, "Sequence". The entity consists of 2 attributes "seqForWk1CD" & "seqForWk2CD".
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
SequenceMO *seqEntity = [NSEntityDescription
insertNewObjectForEntityForName:#"Sequence"
inManagedObjectContext:context];
// some other code
seqEntity.seqForWk1CD = arrForWk1;
seqEntity.seqForWk2CD = arrForWk2;
NSLog(#"%#", arrForWk1);
NSLog(#"%#", arrForWk2);
NSError *error = nil;
if (context != nil) {
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
When printed, the arrays will always display the contents of the array.
This is where I try to fetch the data.
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Sequence" inManagedObjectContext:context];
[request setEntity:entity];
NSError *error;
if(![context save:&error]){
NSLog(#"Error fetching. %# %#", error, [error localizedDescription]);
}
NSUInteger count = [context countForFetchRequest:request error:&error];
if(count != 0){
NSArray *fetchObj = [context executeFetchRequest:request error:&error];
NSManagedObject *sequence = (NSManagedObject *)[fetchObj objectAtIndex:0];
NSLog(#"1 - %#", sequence);
arrForWk1 = [sequence valueForKey:#"seqForWk1CD"];
NSLog(#"%#", arrForWk1);
arrForWk2 = [sequence valueForKey:#"seqForWk2CD"];
NSLog(#"%#", arrForWk2);
}
The problem comes when I restart the application. The arrays either show (null) for both arrays or it shows the contents of both of the arrays. The if statement for if(![context save:&error]) never gets triggered. Subclasses of NSManagedObject for the entity has already been added.I've also tried declaring the AppDelegate in #interface and forced to save the context immediately by doing [delegate saveContext];.Here is the method where the saving happens. "check" is initialized to 0 at the viewDidLoad method. Both "arrForWk1" & "arrForWk2" are declared at #interface.
- (IBAction)randomizeSequence:(UIButton *)sender {
NSMutableArray *storeArray = [[NSMutableArray alloc] init];
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
SequenceMO *seqEntity = [NSEntityDescription insertNewObjectForEntityForName:#"Sequence" inManagedObjectContext:context];
BOOL record = NO;
int x;
for (int i=0; [storeArray count] < 9; i++) //Loop for generate different random values
{
x = 1 + arc4random() % 9;//generating random number
if(i==0)//for first time
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
else
{
for (int j=0; j<= [storeArray count]-1; j++)
{
if (x ==[[storeArray objectAtIndex:j] intValue])
record = YES;
}
if (record == YES)
{
record = NO;
}
else
{
[storeArray addObject:[NSNumber numberWithInt:x]];
}
}
}
check++;
if(check == 1 ) {
arrForWk1 = storeArray;
[self.wk1Seq reloadData];
}
else if(check == 2) {
arrForWk2 = storeArray;
seqEntity.seqForWk1CD = arrForWk1;
seqEntity.seqForWk2CD = arrForWk2;
NSError *error = nil;
if (context != nil) {
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
[self.wk2Seq reloadData];
}
Just to add on, the arrays are of data type NSMutableArray and I'm trying to store them into attributes of type "Transformable".
After researching around I managed to solve the problem. I'm not sure how it actually works but I solved it by rearranging the code when I'm trying to fetch the data.
AppDelegate *delegate = [[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSEntityDescription *descriptor = [NSEntityDescription entityForName:#"Sequence" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
request.entity = descriptor;
NSError *error;
NSArray *fetchObj = [context executeFetchRequest:request error:&error];
if(fetchObj == nil) {
NSLog(#"Error occured when trying to fetch.");
}
else {
if(fetchObj.count == 0) {
NSLog(#"No objects saved");
else {
NSManagedObject *sequence = (NSManagedObject *)[fetchObj objectAtIndex:0];
NSLog(#"1 - %#", sequence);
arrForWk1 = [sequence valueForKey:#"seqForWk1CD"];
NSLog(#"%#", arrForWk1);
arrForWk2 = [sequence valueForKey:#"seqForWk2CD"];
NSLog(#"%#", arrForWk2);
NSLog(#"2 - %#", sequence);
}
I've tried also tried 2 ways of saving the data. In the if statement where I tried to save the data, I converted the NSMutableArrays to NSArrays.
else if(check == 2) {
test2 = storeArray;
NSManagedObjectContext *context = [delegate managedObjectContext];
SequenceMO *seqEntity = [NSEntityDescription insertNewObjectForEntityForName:#"Sequence" inManagedObjectContext:context];
NSArray *tArr = [arrForWk1 copy];
NSArray *tArr2 = [arrForWk2 copy];
seqEntity.seqForWk1CD = tArr;
seqEntity.seqForWk2CD = tArr2;
NSError *error = nil;
if (context != nil) {
if ([context hasChanges] && ![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
The second way I tried is by using an answer from Core Data not saving changes to Transformable property
id temp = [seqEntity seqForWk1CD];
id temp2 = [seqEntity seqForWk2CD];
temp = arrForWk1;
temp2 = arrForWk2;
[seqEntity setSeqForWk1CD:temp];
[seqEntity setSeqForWk2CD:temp2];
Apparently it worked somehow.

CoreData objects not saved between screens

I have a screen that holds a UITableView, in this screen I have an array of NSManagedObjects. It's working just fine, but as I try move to another screen (click on a specific cell, and push a new screen), then return to the same UITableView screen, all the objects got lost.
What does it means? I try to print the array of the NSManagedObjects and it's fine, all the objects there, but as I print the description of each object, I get nil from all the object attributes.
Someone knows whats the cause of it? I don't know why but it worked just fine 12 hours ago, but now it's all messed up and I don't have a clue what have I done.
Thanks in advance!
Save method:
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
else {
NSLog(#"Context saved!");
}
}
}
This is how I save the objects:
NSDictionary *response = responseObject;
if ([[response valueForKey:#"status"] rangeOfString:#"ok"].location != NSNotFound)
{
NSArray *data = [response objectForKey:#"data"];
if (data.count != 0)
{
if (page.integerValue == 0) {
[[DownloadData sharedData] deleteAllObjectsFromEntityName:#"DbHomeCuisine"];
[[DownloadData sharedData] deleteAllObjectsFromEntityName:#"DbHomeCategory"];
[[DownloadData sharedData] deleteAllObjectsFromEntityName:#"DbHomeDish"];
}
NSMutableArray *homePageObjects = [[NSMutableArray alloc] initWithCapacity:data.count];
for (NSDictionary *object in data)
{
NSNumber *type = [object objectForKey:#"type"];
switch (type.integerValue) {
case 1:
{
NSDictionary *content = [object objectForKey:#"content"];
NSManagedObjectContext *context = [[MainDb sharedDb] managedObjectContext];
DbHomeCuisine *homeCuisine = [NSEntityDescription insertNewObjectForEntityForName:#"DbHomeCuisine" inManagedObjectContext:context];
NSInteger cuisineId = [[content valueForKey:#"cuisine_id"] integerValue];
homeCuisine.cuisine = [self gCuisineWithCuisineId:[NSNumber numberWithInteger:cuisineId]];
NSInteger count = [[content valueForKey:#"count"] integerValue];
homeCuisine.count = [NSNumber numberWithInteger:count];
homeCuisine.type = type;
[homePageObjects addObject:homeCuisine];
}
break;
case 2:
{
NSDictionary *content = [object objectForKey:#"content"];
NSManagedObjectContext *context = [[MainDb sharedDb] managedObjectContext];
DbHomeCategory *homeCategory = [NSEntityDescription insertNewObjectForEntityForName:#"DbHomeCategory" inManagedObjectContext:context];
NSInteger categoryId = [[content valueForKey:#"category_id"] integerValue];
homeCategory.category = [self gCategoryWithCategoryId:[NSNumber numberWithInteger:categoryId]];
NSInteger count = [[content valueForKey:#"count"] integerValue];
homeCategory.count = [NSNumber numberWithInteger:count];
homeCategory.type = type;
[homePageObjects addObject:homeCategory];
}
break;
case 3:
{
NSDictionary *content = [object objectForKey:#"content"];
NSManagedObjectContext *context = [[MainDb sharedDb] managedObjectContext];
DbHomeDish *homeDish = [NSEntityDescription insertNewObjectForEntityForName:#"DbHomeDish" inManagedObjectContext:context];
homeDish.dishId = [self gInt:content forKey:#"dish_id"];
homeDish.headline = [AppUtils checkForEmptyValue:[content valueForKey:#"title"]];
homeDish.text = [AppUtils checkForEmptyValue:[content valueForKey:#"description"]];
homeDish.cuisineId = [self gInt:content forKey:#"cuisine_id"];
homeDish.cuisine = [self gCuisineWithCuisineId:homeDish.cuisineId];
homeDish.creationDate = [AppUtils checkForEmptyValue:[content valueForKey:#"creation_time"]];
homeDish.userId = [self gInt:content forKey:#"user_id"];
homeDish.longitude = [self gDouble:content forKey:#"lng"];
homeDish.latitude = [self gDouble:content forKey:#"lat"];
homeDish.lastPromoteDate = [AppUtils checkForEmptyValue:[content valueForKey:#"last_promote_time"]];
homeDish.price = [self gInt:content forKey:#"price"];
homeDish.currency = [AppUtils checkForEmptyValue:[content valueForKey:#"currency"]];
homeDish.countryName = [AppUtils checkForEmptyValue:[content valueForKey:#"country_name"]];
homeDish.baseCurrency = [self gFloat:content forKey:#"base_currency"];
homeDish.exchangeRate = [self gFloat:content forKey:#"exchange_rate"];
homeDish.countryIsoCode = [AppUtils checkForEmptyValue:[content valueForKey:#"country_iso_code"]];
homeDish.mainPhoto = [AppUtils checkForEmptyValue:[content valueForKey:#"main_photo"]];
homeDish.like = [self gLikeWithDishId:homeDish.dishId];
homeDish.profileImageURL = [AppUtils checkForEmptyValue:[content valueForKey:#"profile_img_url"]];
homeDish.likeCount = [self gInt:content forKey:#"likes"];
homeDish.type = type;
[homePageObjects addObject:homeDish];
}
break;
default:
break;
}
}
// ##log -- Save data to core data and device
//
//
[[MainDb sharedDb] saveContext];
if (success) {
success(operation, homePageObjects);
}
}
}
Seriously, you should consider refactoring using a NSFetchedResultsController. Start from the template provided in Xcode (New Project -> Master/Detail -> check Core Data, the code is in MasterViewController.m).
I strongly discourage loading Core Data objects into an array to be displayed in a table view. Your problem is typical for such a setup, and you will run into memory and performance issues eventually as well.

NSManagedObjectContext work well only a few times, then it stops working

After I tried to ask twice and explain myself, I did a dig and I think I can now explain my problem better:
1) I'm using core data to save to NSManagedObjects: CoreDataTrap & CoreDataAllTraps.
First time, I'm parsing a large xml and then convert to array and then add the details to CoreDataAllTraps, this operation going well as I know because I did a log.
2) Then, Just for the test, I'm fetching all of the records and log the total number of them.
Those functions give me the correct number of records.
3) Then just initializing a few variables.
4) Then initializing my quad tree.
Which gives me back my assertion error.
Error: fetchedObjects have no records.
5) Then, all the rest of the functions that using core data gives me error back of course, because there is no data.
Relevant (numbered) code:
1:
---
- (void)addOrUpdateTrap:(Traps*)trapObject
{
NSManagedObjectContext *context = generateManagedObjectContext();
int trapID = trapObject.getTrapID;
CoreDataAllTraps *trapEntity = nil;
NSError *error = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:kCORE_DATA_ALL_TRAPS_ENTITY];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"trapID == %d", trapID];
[fetchRequest setPredicate:predicate];
NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
if (results == nil)
{
// Handle error
}
else if (results.count == 0)
{
// Nothing to update, add new trap
// Create a new record (row)
trapEntity = [NSEntityDescription insertNewObjectForEntityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:context];
}
else
{
trapEntity = results[0]; // There should be only one object for the ID.
}
if (trapEntity != nil)
{
// Set properties for new or existing object ...
// Int
[trapEntity setTrapID:[NSNumber numberWithInt:trapObject.getTrapID]];
[trapEntity setType:[NSNumber numberWithInt:trapObject.getTrapType]];
[trapEntity setDist:[NSNumber numberWithInt:trapObject.getTrapDistanceToCar]];
[trapEntity setDist_to_close_point:[NSNumber numberWithInt:trapObject.getTrapDistanceToClosePoint]];
[trapEntity setActive:[NSNumber numberWithInt:trapObject.isActive]];
[trapEntity setAlert:[NSNumber numberWithInt:trapObject.isAlert]];
[trapEntity setAlarmDistance:[NSNumber numberWithInt:trapObject.alarmDistance]];
[trapEntity setRoadNumber:[NSNumber numberWithInt:trapObject.roadNumber]];
[trapEntity setPolys:[NSNumber numberWithInt:trapObject.polygons]];
[trapEntity setEnter_to_area:[NSNumber numberWithInt:trapObject.getTrapEnterToArea]];
// Double
[trapEntity setLat:[NSNumber numberWithDouble:trapObject.getTrapLat]];
[trapEntity setLon:[NSNumber numberWithDouble:trapObject.getTrapLon]];
[trapEntity setClose_point_lat:[NSNumber numberWithDouble:trapObject.getTrapClosePointLat]];
[trapEntity setClose_point_lon:[NSNumber numberWithDouble:trapObject.getTrapClosePointLon]];
// NSString
[trapEntity setLastTrapAlarm:[NSString stringWithFormat:#"%li", trapObject.getTrapLastAlarm]];
[trapEntity setPoly0:trapObject.getTrapPolygonA];
[trapEntity setPoly1: trapObject.getTrapPolygonB];
[trapEntity setPoly2: trapObject.getTrapPolygonC];
[trapEntity setPolygonAzimut1: trapObject.getTrapPolygonAzimuthA];
[trapEntity setPolygonAzimut2: trapObject.getTrapPolygonAzimuthB];
[trapEntity setPolygonAzimut3: trapObject.getTrapPolygonAzimuthC];
[trapEntity setDesc: trapObject.getTrapDesc];
// etc. for all properties ...
error = nil;
if ([context save:&error] == NO) {
NSLog(#"%s error saving: %#\n%#", __PRETTY_FUNCTION__, error.localizedDescription, error.userInfo);
}
else {
[context reset];
}
}
}
2:
---
- (void)saveArray:(NSArray*)array
{
kNETROADS_CONTEXT.arrayOfAllTraps = self.arrayOfAllTraps = array.mutableCopy;
NSLog(#"Total number of traps: %d", self.arrayOfAllTraps.count);
NSManagedObjectContext *context = generateManagedObjectContext();
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
NSLog(#"TrapService - fetchedObjects.count: %d", fetchedObjects.count);
if (fetchedObjects == nil || fetchedObjects.count == 0) {
NSLog(#"saveArray - localizedDescription: %#, userInfo: %#", error.localizedDescription, error.userInfo);
}
[self readArray];
}
- (void)readArray
{
NSManagedObjectContext *context = generateManagedObjectContext();
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
NSLog(#"readArray - fetchedObjects.count: %d", fetchedObjects.count);
if (fetchedObjects == nil || fetchedObjects.count == 0) {
NSLog(#"readArray - localizedDescription: %#, userInfo: %#", error.localizedDescription, error.userInfo);
}
}
3:
---
- (void)initVariables
{
db = [[DataBase alloc] init];
//dbat = [[DataBaseAllTraps alloc] init];
dbat = [DataBaseAllTraps getInstance];
kRECEIVER_CONTEXT.db = [[DataBase alloc] init];
[db deleteTrapsTable];
[dbat deleteTrapsTable];
self.dictAddUserLocations = [[NSMutableDictionary alloc] init];
self.arrayOfAllTraps = [Netroads sharedInstance].arrayOfAllTraps;
self.arrayOfLocations = [[NSMutableArray alloc] init];
self.firstOnLocationChanged = YES;
self.mLocation = [CLLocation new];
self.mLastLocation = [CLLocation new];
self.globalLocation = [CLLocation new];
self.lastGlobalLocation = [CLLocation new];
self.myLocations = [[NSMutableArray alloc] init];
self.accuracy = #"N/A";
self.closeTrap = [[Traps alloc] init];
self.notification = [NSNotificationCenter defaultCenter];
// [self.notification addObserver:self selector:#selector(onReceive:) name:kSend_To_Receiver_Notification object:nil];
}
4:
---
- (void)initializeQuadTree
{
self.qTree = [[QuadTree alloc] init];
BOOL success = YES;
NSManagedObjectContext *context = generateManagedObjectContext();
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:kCORE_DATA_ALL_TRAPS_ENTITY inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil || fetchedObjects.count == 0)
{
NSLog(#"initializeQuadTree - localizedDescription: %#, userInfo: %#", error.localizedDescription, error.userInfo);
success = NO;
}
NSLog(#"initializeQuadTree - fetchedObjects.count: %d", fetchedObjects.count);
NSAssert(fetchedObjects != nil, #"Error: fetchedObjects = nil");
NSAssert(fetchedObjects.count > 0, #"Error: fetchedObjects have no records.");
if (success)
{
for (CoreDataAllTraps *trap in fetchedObjects)
{
double latitude = trap.lat.doubleValue;
double longitude = trap.lon.doubleValue;
double closePointLat = trap.close_point_lat.doubleValue;
double closePointLon = trap.close_point_lon.doubleValue;
DummyAnnotation *trapAnnotation = [[DummyAnnotation alloc] init];
if (closePointLat != 0.0 || closePointLon != 0.0) trapAnnotation.coordinate = CLLocationCoordinate2DMake(closePointLat, closePointLon);
else trapAnnotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
[self.qTree insertObject:trapAnnotation];
}
}
else
{
for (Traps *trap in kNETROADS_CONTEXT.arrayOfAllTraps)
{
double latitude = trap.lat;
double longitude = trap.lon;
double closePointLat = trap.closePointLat;
double closePointLon = trap.closePointLon;
DummyAnnotation *trapAnnotation = [[DummyAnnotation alloc] init];
if (closePointLat != 0.0 || closePointLon != 0.0) trapAnnotation.coordinate = CLLocationCoordinate2DMake(closePointLat, closePointLon);
else trapAnnotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
[self.qTree insertObject:trapAnnotation];
}
}
NSLog(#"TOTAL NUMBER OF TRAPS (%s): %i", __PRETTY_FUNCTION__, success?fetchedObjects.count:[Netroads sharedInstance].arrayOfAllTraps.count);
}
Side notes:
* After calling initializeQuadTree i'm initializing the location manager.
* In location manager I've a dispatch_async that wrap the whole code inside.
* After I done with all initializing, the main of the code happens via location manager didUpdateLocations.
* For each and every using in core data I'm generating new NSManagedObjectConext like this:
FOUNDATION_EXPORT NSManagedObjectContext *generateManagedObjectContext()
{
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator;
return context;
}
[db deleteTrapsTable];
[dbat deleteTrapsTable];
The table deleted after you create it

Core data executeFetchRequest fail with exc_bad_access

From my understanding, this is a memory issue, especially since I call the method from several places several times with different timers.
Code below that throw the exception:
- (NSMutableArray*)getAllTraps
{
#synchronized(self)
{
self.fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Trap"];
NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:self.fetchRequest error:&error];
if (!results)
{
NSLog(#"Error fetching traps: %#", error.localizedDescription);
NSLog(#"Reason: %#", error.localizedFailureReason);
NSLog(#"Suggestion: %#", error.localizedRecoverySuggestion);
abort();
}
if (error != nil)
{
// Handle error
NSLog(#"Error getting all traps");
}
else
{
// Handle success
NSLog(#"Success getting all traps");
}
NSMutableArray *arrayOfAllTraps = [[NSMutableArray alloc] init];
for (int i = 0; i < results.count; i++)
{
Trap *singleTrap = results[i];
NSMutableDictionary *singleDict = [[NSMutableDictionary alloc] init];
if (singleTrap.trapID.integerValue > 0)
{
singleDict[ID] = singleTrap.trapID;
singleDict[ALARMDISTANCE] = singleTrap.alarmDistance;
singleDict[ISACTIVE] = singleTrap.isActive;
singleDict[LAT] = singleTrap.lat;
singleDict[LON] = singleTrap.lon;
singleDict[POLYGONS] = singleTrap.polys;
// NSLog(#"Trap ID: %#, Trap Description: %#", singleTrap.trapID, singleTrap.trapDescription);
singleDict[DESCRIPTION] = singleTrap.trapDescription;
singleDict[ROADNUMBER] = singleTrap.roadNumber;
singleDict[TYPE] = singleTrap.type;
singleDict[DEGREES] = singleTrap.degrees;
singleDict[DIRECTION] = singleTrap.direction;
if (singleTrap.poly0 == nil)
{
singleDict[POLYGON_A] = #"";
}
else
{
singleDict[POLYGON_A] = singleTrap.poly0;
}
// Make sure not to set NULL value #1
if (singleTrap.poly1 == nil)
{
singleDict[POLYGON_B] = #"";
}
else
{
singleDict[POLYGON_B] = singleTrap.poly1;
}
if (singleTrap.poly2 == nil)
{
singleDict[POLYGON_C] = #"";
}
else
{
singleDict[POLYGON_C] = singleTrap.poly2;
}
// Make sure not to set NULL value #2
if (singleTrap.polygonAzimut1 == nil)
{
singleDict[POLYGON_A_AZIMUTH] = #"";
}
else
{
singleDict[POLYGON_A_AZIMUTH] = singleTrap.polygonAzimut1;
}
if (singleTrap.polygonAzimut2 == nil)
{
singleDict[POLYGON_B_AZIMUTH] = #"";
}
else
{
singleDict[POLYGON_B_AZIMUTH] = singleTrap.polygonAzimut2;
}
if (singleTrap.polygonAzimut3 == nil)
{
singleDict[POLYGON_C_AZIMUTH] = #"";
}
else
{
singleDict[POLYGON_C_AZIMUTH] = singleTrap.polygonAzimut3;
}
[arrayOfAllTraps addObject:singleDict];
}
}
return arrayOfAllTraps;
}
}
The fail come right after:
NSArray *results = [self.managedObjectContext executeFetchRequest:self.fetchRequest error:&error];
And not even go inside 'if'.
Try this,
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:#"Trap" inManagedObjectContext:self.managedObjectContext];
[fetch setEntity:entityDescription];
NSError * error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetch error:&error];

CoreData and NSManagedObjectContext

I've got this function that will move objects from a "fallbackstore" to the iCloud store, fallbackstore is the store where objects where saved when iCloud is unavailable.
Bottom line, I need to move objects (with their relationship) from one context to another one.
But I'm getting this error:
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Context already has a coordinator; cannot replace.'
* First throw call stack:
on:
foodSuccess = [moc save:&localError];
Anybody knows where I'm getting wrong (and why)? Thanks in advance!
- (BOOL)seedStore:(NSPersistentStore *)store withPersistentStoreAtURL:(NSURL *)seedStoreURL error:(NSError * __autoreleasing *)error {
BOOL success = YES;
NSLog(#"%s", __func__);
BOOL foodSuccess = YES;
BOOL sportSuccess = YES;
BOOL dailySuccess = YES;
BOOL activitySuccess = YES;
BOOL reportSuccess = YES;
BOOL userSuccess = YES;
BOOL ingredientSuccess = YES;
NSUInteger batchSize = 5000;
NSError *localError = nil;
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *seedPSC = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSDictionary *seedStoreOptions = #{ NSReadOnlyPersistentStoreOption : [NSNumber numberWithBool:YES] };
NSPersistentStore *seedStore = [seedPSC addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:seedStoreURL
options:seedStoreOptions
error:&localError];
if (seedStore) {
NSManagedObjectContext *seedMOC = [[NSManagedObjectContext alloc] init];
[seedMOC setPersistentStoreCoordinator:seedPSC];
// Food
NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:#"Food"];
fr.relationshipKeyPathsForPrefetching = #[#"daily", #"ingredient", #"ingredients"];
[fr setFetchBatchSize:batchSize];
NSArray *foods = [seedMOC executeFetchRequest:fr error:&localError];
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[moc setPersistentStoreCoordinator:_psc];
NSUInteger i = 1;
for (Food *f in foods) {
[self addFood:f toStore:store withContext:moc];
if (0 == (i % batchSize)) {
foodSuccess = [moc save:&localError];
if (foodSuccess) {
[moc reset];
} else {
NSLog(#"Error saving during seed (Food): %#", localError);
break;
}
}
i++;
}
if ([moc hasChanges]) {
foodSuccess = [moc save:&localError];
[moc reset];
}
// Sport
NSFetchRequest *fetchSports = [NSFetchRequest fetchRequestWithEntityName:#"Sport"];
fetchSports.relationshipKeyPathsForPrefetching = #[#"activity"];
fetchSports.fetchBatchSize = batchSize;
NSArray *sports = [seedMOC executeFetchRequest:fetchSports error:&localError];
NSManagedObjectContext *sportContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
sportContext.persistentStoreCoordinator = _psc;
NSUInteger iSports = 1;
for (Sport *s in sports) {
[self addSport:s toStore:store withContext:sportContext];
if (0 == (iSports % batchSize)) {
sportSuccess = [moc save:&localError];
if (sportSuccess) {
[moc reset];
} else {
NSLog(#"Error saving during seed (Sport): %#", localError);
break;
}
}
iSports++;
}
if ([sportContext hasChanges]) {
sportSuccess = [sportContext save:&localError];
[sportContext reset];
}
// Daily
NSFetchRequest *fetchDailies = [NSFetchRequest fetchRequestWithEntityName:#"Daily"];
fetchDailies.relationshipKeyPathsForPrefetching = #[#"food", #"user"];
fetchDailies.fetchBatchSize = batchSize;
NSArray *dailies = [seedMOC executeFetchRequest:fetchDailies error:&localError];
NSManagedObjectContext *dailiesContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
dailiesContext.persistentStoreCoordinator = _psc;
NSUInteger iDailies = 1;
for(Daily *d in dailies) {
[self addDaily:d toStore:store withContext:dailiesContext];
if(0 == (iDailies % batchSize)) {
dailySuccess = [dailiesContext save:&localError];
if (dailySuccess) {
[dailiesContext reset];
}
else {
NSLog(#"Error saving during seed (Daily): %#", localError);
break;
}
}
iDailies++;
}
if ([dailiesContext hasChanges]) {
dailySuccess = [dailiesContext save:&localError];
[dailiesContext reset];
}
// Ingredient
NSFetchRequest *fetchIngredients = [NSFetchRequest fetchRequestWithEntityName:#"Ingredient"];
fetchIngredients.relationshipKeyPathsForPrefetching = #[#"food", #"foods"];
fetchIngredients.fetchBatchSize = batchSize;
NSArray *ingredients = [seedMOC executeFetchRequest:fetchIngredients error:&localError];
NSManagedObjectContext *ingredientsContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
ingredientsContext.persistentStoreCoordinator = _psc;
NSUInteger iIngredients = 1;
for(Ingredient *i in ingredients) {
[self addIngredient:i toStore:store withContext:ingredientsContext];
if(0 == (iIngredients % batchSize)) {
ingredientSuccess = [ingredientsContext save:&localError];
if (ingredientSuccess) {
[ingredientsContext reset];
}
else {
NSLog(#"Error saving during seed (Ingredient): %#", localError);
break;
}
}
iIngredients++;
}
if ([ingredientsContext hasChanges]) {
ingredientSuccess = [ingredientsContext save:&localError];
[ingredientsContext reset];
}
// Activity
NSFetchRequest *fetchActivities = [NSFetchRequest fetchRequestWithEntityName:#"Activity"];
fetchActivities.relationshipKeyPathsForPrefetching = #[#"sport", #"user"];
fetchActivities.fetchBatchSize = batchSize;
NSArray *activities = [seedMOC executeFetchRequest:fetchActivities error:&localError];
NSManagedObjectContext *activitiesContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
dailiesContext.persistentStoreCoordinator = _psc;
NSUInteger iActivities = 1;
for(Activity *a in activities) {
[self addActivity:a toStore:store withContext:activitiesContext];
if(0 == (iActivities % batchSize)) {
activitySuccess = [activitiesContext save:&localError];
if (activitySuccess) {
[activitiesContext reset];
}
else {
NSLog(#"Error saving during seed (Activity): %#", localError);
break;
}
}
iActivities++;
}
if ([activitiesContext hasChanges]) {
activitySuccess = [activitiesContext save:&localError];
[activitiesContext reset];
}
// Report
NSFetchRequest *fetchReports = [NSFetchRequest fetchRequestWithEntityName:#"Report"];
fetchReports.relationshipKeyPathsForPrefetching = #[#"user"];
fetchReports.fetchBatchSize = batchSize;
NSArray *reports = [seedMOC executeFetchRequest:fetchReports error:&localError];
NSManagedObjectContext *reportsContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
reportsContext.persistentStoreCoordinator = _psc;
NSUInteger iReports = 1;
for(Report *r in reports) {
[self addReport:r toStore:store withContext:reportsContext];
if(0 == (iReports % batchSize)) {
reportSuccess = [reportsContext save:&localError];
if (reportSuccess) {
[reportsContext reset];
}
else {
NSLog(#"Error saving during seed (Report): %#", localError);
break;
}
}
iReports++;
}
if ([reportsContext hasChanges]) {
reportSuccess = [reportsContext save:&localError];
[reportsContext reset];
}
// User
NSFetchRequest *fetchUsers = [NSFetchRequest fetchRequestWithEntityName:#"User"];
fetchUsers.relationshipKeyPathsForPrefetching = #[#"activities", #"dailies", #"reports"];
fetchUsers.fetchBatchSize = batchSize;
NSArray *users = [seedMOC executeFetchRequest:fetchUsers error:&localError];
NSManagedObjectContext *usersContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
usersContext.persistentStoreCoordinator = _psc;
NSUInteger iUsers = 1;
for(User *u in users) {
[self addUser:u toStore:store withContext:usersContext];
if(0 == (iUsers % batchSize)) {
userSuccess = [usersContext save:&localError];
if (userSuccess) {
[usersContext reset];
}
else {
NSLog(#"Error saving during seed (User): %#", localError);
break;
}
}
iUsers++;
}
if ([usersContext hasChanges]) {
userSuccess = [usersContext save:&localError];
[usersContext reset];
}
// Result
success = foodSuccess && sportSuccess && dailySuccess && ingredientSuccess && activitySuccess && reportSuccess && userSuccess;
} else {
success = NO;
NSLog(#"Error adding seed store: %#", localError);
}
if (NO == success) {
if (localError && (error != NULL)) {
*error = localError;
}
}
return success;
}
- (void)addFood:(Food *)food toStore:(NSPersistentStore *)store withContext:(NSManagedObjectContext *)moc
{
NSEntityDescription *entity = [food entity];
Food *newFood = [[Food alloc] initWithEntity:entity insertIntoManagedObjectContext:moc];
newFood.alcol = food.alcol;
newFood.amid = food.amid;
newFood.bookmark = food.bookmark;
newFood.calcium = food.calcium;
newFood.cho = food.cho;
newFood.cholesterol = food.cholesterol;
newFood.complex = food.complex;
newFood.copper = food.copper;
newFood.dirty = food.dirty;
newFood.edible = food.edible;
newFood.fat = food.fat;
newFood.fatMono = food.fatMono;
newFood.fatPoli = food.fatPoli;
newFood.fatSat = food.fatSat;
newFood.fibre = food.fibre;
newFood.iron = food.iron;
newFood.kcal = food.kcal;
newFood.lookback = food.lookback;
newFood.magnesium = food.magnesium;
newFood.name = food.name;
newFood.note = food.note;
newFood.phosphorus = food.phosphorus;
newFood.potassium = food.potassium;
newFood.pro = food.pro;
newFood.recipe = food.recipe;
newFood.recordUUID = (food.recordUUID == nil) ? [[[NSUUID alloc] init] UUIDString] : food.recordUUID;
newFood.serving = food.serving;
newFood.servingDesc = food.servingDesc;
newFood.sodium = food.sodium;
newFood.userAdd = food.userAdd;
newFood.vitA = food.vitA;
newFood.vitC = food.vitC;
newFood.vitE = food.vitE;
newFood.water = food.water;
newFood.zinc = food.zinc;
newFood.dosePeople = food.dosePeople;
newFood.daily = food.daily;
for(Ingredient *i in food.ingredients) {
NSEntityDescription *entityIngredient = [i entity];
Ingredient *newIngredient = [[Ingredient alloc] initWithEntity:entityIngredient insertIntoManagedObjectContext:moc];
[newFood addIngredientsObject:newIngredient];
}
NSMutableSet *ing = [food mutableSetValueForKey:#"ingredient"];
for(Ingredient *i in ing) {
NSLog(#"%s Name: %#", __func__, i.food.name);
NSEntityDescription *entityIngredient = [i entity];
Ingredient *newIngredient = [[Ingredient alloc] initWithEntity:entityIngredient insertIntoManagedObjectContext:moc];
[newFood addIngredientsObject:newIngredient];
}
[moc assignObject:newFood toPersistentStore:store];
}
It might or might not be the cause for the error you're getting but if you initialize a MOC with NSPrivateQueueConcurrencyType you should strictly access it through -performBlock: and -performBlockAndWait:. See this related question.

Resources