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.
Related
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.
I am very new to Core Data and have been trying to following many tutorials, but most of them put all of the Core Data methods into AppDelegate.so any one help me please Thanks in advance
- (NSFetchedResultsController *)fetchedResultsController
{
// NSLog(#"Calling fetchedResultsController # rootviewController");
if (is_Searching && [search_string length])
{
NSManagedObjectContext *moc = [[AppDelegate appdelegate] managedObjectContext_roster];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:#"sectionNum" ascending:YES];
NSSortDescriptor *sd2 = [[NSSortDescriptor alloc] initWithKey:#"displayName" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, sd2, nil];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSMutableArray * predicateArray = [[NSMutableArray alloc]init];
if (is_Searching && [search_string length]) {
NSPredicate *predecate = [NSPredicate predicateWithFormat:#"displayName CONTAINS [c] %#",search_string];
[predicateArray addObject:predecate];
}
if ([[AppDelegate get_update_privacy_Array] count]) {
for (NSString * jids in [AppDelegate get_update_privacy_Array]) {
NSPredicate *predecate_blocked = [NSPredicate predicateWithFormat:#"NOT(nickname CONTAINS [c] %# OR jidStr CONTAINS %#)" ,jids, jids];
[predicateArray addObject:predecate_blocked];
}
}
NSPredicate *predicate_final = [NSCompoundPredicate andPredicateWithSubpredicates:
predicateArray];
[fetchRequest setPredicate:predicate_final];
[fetchRequest setEntity:entity];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:10];
fetchedResultsController_search = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:#"sectionNum"
cacheName:nil];
[fetchedResultsController_search setDelegate:self];
NSError *error = nil;
if (![fetchedResultsController_search performFetch:&error])
{
//DDLogError(#"Error performing fetch: %#", error);
}
if (![[fetchedResultsController_search fetchedObjects]count] && ![groupChatArray count]) {
[AppDelegate alertWithTitle:#"Alert" message:#"No contact found!"];
}
return fetchedResultsController_search;
}
else
{
NSManagedObjectContext *moc = [[AppDelegate appdelegate] managedObjectContext_roster];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
NSSortDescriptor *sd1 = [[NSSortDescriptor alloc] initWithKey:#"sectionNum" ascending:YES];
NSSortDescriptor *sd2 = [[NSSortDescriptor alloc] initWithKey:#"displayName" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sd1, sd2, nil];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSMutableArray *predicateArray = [[NSMutableArray alloc]init];
if ([[AppDelegate get_update_privacy_Array] count]) {
for (NSString * jids in [AppDelegate get_update_privacy_Array]) {
NSPredicate *predecate_blocked = [NSPredicate predicateWithFormat:#"NOT(nickname CONTAINS [c] %# OR jidStr CONTAINS %#)" ,jids, jids];
[predicateArray addObject:predecate_blocked];
}
}
NSPredicate *predicate_final = [NSCompoundPredicate andPredicateWithSubpredicates:
predicateArray];
[fetchRequest setPredicate:predicate_final];
[fetchRequest setEntity:entity];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:10];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc
sectionNameKeyPath:#"sectionNum"
cacheName:nil];
[fetchedResultsController setDelegate:self];
NSError *error = nil;
if (![fetchedResultsController performFetch:&error])
{
//DDLogError(#"Error performing fetch: %#", error);
}
return fetchedResultsController;
}
}
XMPPUserCoreDataStorageObject.m class
#import "XMPP.h"
#import "XMPPRosterCoreDataStorage.h"
#import "XMPPUserCoreDataStorageObject.h"
#import "XMPPResourceCoreDataStorageObject.h"
#import "XMPPGroupCoreDataStorageObject.h"
#import "NSNumber+XMPP.h"
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
#interface XMPPUserCoreDataStorageObject ()
#property(nonatomic,strong) XMPPJID *primitiveJid;
#property(nonatomic,strong) NSString *primitiveJidStr;
#property(nonatomic,strong) NSString *primitiveDisplayName;
#property(nonatomic,assign) NSInteger primitiveSection;
#property(nonatomic,strong) NSString *primitiveSectionName;
#property(nonatomic,strong) NSNumber *primitiveSectionNum;
#end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#implementation XMPPUserCoreDataStorageObject
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Accessors
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#dynamic jid, primitiveJid;
#dynamic jidStr, primitiveJidStr;
#dynamic streamBareJidStr;
#dynamic nickname;
#dynamic displayName, primitiveDisplayName;
#dynamic subscription;
#dynamic ask;
#dynamic unreadMessages;
#dynamic photo;
#dynamic section, primitiveSection;
#dynamic sectionName, primitiveSectionName;
#dynamic sectionNum, primitiveSectionNum;
#dynamic groups;
#dynamic primaryResource;
#dynamic resources;
#dynamic status;
- (XMPPJID *)jid
{
// Create and cache the jid on demand
[self willAccessValueForKey:#"jid"];
XMPPJID *tmp = [self primitiveJid];
[self didAccessValueForKey:#"jid"];
if (tmp == nil) {
tmp = [XMPPJID jidWithString:[self jidStr]];
[self setPrimitiveJid:tmp];
}
return tmp;
}
- (void)setJid:(XMPPJID *)jid
{
self.jidStr = [jid bare];
}
- (void)setJidStr:(NSString *)jidStr
{
[self willChangeValueForKey:#"jidStr"];
[self setPrimitiveJidStr:jidStr];
[self didChangeValueForKey:#"jidStr"];
// If the jidStr changes, the jid becomes invalid.
[self setPrimitiveJid:nil];
}
- (NSInteger)section
{
// Create and cache the section on demand
[self willAccessValueForKey:#"section"];
NSInteger tmp = [self primitiveSection];
[self didAccessValueForKey:#"section"];
// section uses zero, so to distinguish unset values, use NSNotFound
if (tmp == NSNotFound) {
tmp = [[self sectionNum] integerValue];
[self setPrimitiveSection:tmp];
}
return tmp;
}
- (void)setSection:(NSInteger)value
{
self.sectionNum = [NSNumber numberWithInteger:value];
}
- (NSInteger)primitiveSection
{
return section;
}
- (void)setPrimitiveSection:(NSInteger)primitiveSection
{
section = primitiveSection;
}
- (void)setSectionNum:(NSNumber *)sectionNum
{
[self willChangeValueForKey:#"sectionNum"];
[self setPrimitiveSectionNum:sectionNum];
[self didChangeValueForKey:#"sectionNum"];
// If the sectionNum changes, the section becomes invalid.
// section uses zero, so to distinguish unset values, use NSNotFound
[self setPrimitiveSection:NSNotFound];
}
- (NSString *)sectionName
{
// Create and cache the sectionName on demand
[self willAccessValueForKey:#"sectionName"];
NSString *tmp = [self primitiveSectionName];
[self didAccessValueForKey:#"sectionName"];
if (tmp == nil) {
// Section names are organized by capitalizing the first letter of the displayName
NSString *upperCase = [self.displayName uppercaseString];
// return the first character with support UTF-16:
tmp = [upperCase substringWithRange:[upperCase rangeOfComposedCharacterSequenceAtIndex:0]];
[self setPrimitiveSectionName:tmp];
}
return tmp;
}
- (void)setDisplayName:(NSString *)displayName
{
[self willChangeValueForKey:#"displayName"];
[self setPrimitiveDisplayName:displayName];
[self didChangeValueForKey:#"displayName"];
// If the displayName changes, the sectionName becomes invalid.
[self setPrimitiveSectionName:nil];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark NSManagedObject
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)awakeFromInsert
{
// Section uses zero, so to distinguish unset values, use NSNotFound.
self.primitiveSection = NSNotFound;
}
- (void)awakeFromFetch
{
// Section uses zero, so to distinguish unset values, use NSNotFound.
//
// Note: Do NOT use "self.section = NSNotFound" as this will in turn set the sectionNum.
self.primitiveSection = NSNotFound;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Creation & Updates
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ (id)insertInManagedObjectContext:(NSManagedObjectContext *)moc
withJID:(XMPPJID *)jid
streamBareJidStr:(NSString *)streamBareJidStr
{
if (jid == nil)
{
NSLog(#"XMPPUserCoreDataStorageObject: invalid jid (nil)");
return nil;
}
XMPPUserCoreDataStorageObject *newUser;
newUser = [NSEntityDescription insertNewObjectForEntityForName:#"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
newUser.streamBareJidStr = streamBareJidStr;
newUser.jid = jid;
newUser.nickname = nil;
newUser.displayName = [jid bare];
return newUser;
}
+ (id)insertInManagedObjectContext:(NSManagedObjectContext *)moc
withItem:(NSXMLElement *)item
streamBareJidStr:(NSString *)streamBareJidStr
{
NSString *jidStr = [item attributeStringValueForName:#"jid"];
XMPPJID *jid = [XMPPJID jidWithString:jidStr];
if (jid == nil)
{
NSLog(#"XMPPUserCoreDataStorageObject: invalid item (missing or invalid jid): %#", item);
return nil;
}
XMPPUserCoreDataStorageObject *newUser;
newUser = [NSEntityDescription insertNewObjectForEntityForName:#"XMPPUserCoreDataStorageObject"
inManagedObjectContext:moc];
newUser.streamBareJidStr = streamBareJidStr;
[newUser updateWithItem:item];
return newUser;
}
- (void)updateGroupsWithItem:(NSXMLElement *)item
{
XMPPGroupCoreDataStorageObject *group = nil;
// clear existing group memberships first
if ([self.groups count] > 0) {
[self removeGroups:self.groups];
}
NSArray *groupItems = [item elementsForName:#"group"];
NSString *groupName = nil;
for (NSXMLElement *groupElement in groupItems) {
groupName = [groupElement stringValue];
group = [XMPPGroupCoreDataStorageObject fetchOrInsertGroupName:groupName
inManagedObjectContext:[self managedObjectContext]];
if (group != nil) {
[self addGroupsObject:group];
}
}
}
- (void)updateWithItem:(NSXMLElement *)item
{
NSString *jidStr = [item attributeStringValueForName:#"jid"];
XMPPJID *jid = [XMPPJID jidWithString:jidStr];
if (jid == nil)
{
NSLog(#"XMPPUserCoreDataStorageObject: invalid item (missing or invalid jid): %#", item);
return;
}
self.jid = jid;
self.nickname = [item attributeStringValueForName:#"name"];
self.displayName = (self.nickname != nil) ? self.nickname : jidStr;
self.subscription = [item attributeStringValueForName:#"subscription"];
self.ask = [item attributeStringValueForName:#"ask"];
[self updateGroupsWithItem:item];
}
- (void)recalculatePrimaryResource
{
self.primaryResource = nil;
NSArray *sortedResources = [[self allResources] sortedArrayUsingSelector:#selector(compare:)];
if ([sortedResources count] > 0)
{
XMPPResourceCoreDataStorageObject *resource = [sortedResources objectAtIndex:0];
// Primary resource must have a non-negative priority
if ([resource priority] >= 0)
{
self.primaryResource = resource;
if (resource.intShow >= 3)
self.section = 0;
else
self.section = 1;
}
}
if (self.primaryResource == nil)
{
self.section = 2;
}
}
- (void)updateWithPresence:(XMPPPresence *)presence streamBareJidStr:(NSString *)streamBareJidStr
{
XMPPResourceCoreDataStorageObject *resource =
(XMPPResourceCoreDataStorageObject *)[self resourceForJID:[presence from]];
if ([[presence type] isEqualToString:#"unavailable"] || [presence isErrorPresence])
{
if (resource)
{
[self removeResourcesObject:resource];
[[self managedObjectContext] deleteObject:resource];
}
}
else
{
if (resource)
{
[resource updateWithPresence:presence];
}
else
{
XMPPResourceCoreDataStorageObject *newResource;
newResource = [XMPPResourceCoreDataStorageObject insertInManagedObjectContext:[self managedObjectContext]
withPresence:presence
streamBareJidStr:streamBareJidStr];
[self addResourcesObject:newResource];
}
}
[self recalculatePrimaryResource];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark XMPPUser Protocol
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (BOOL)isOnline
{
return (self.primaryResource != nil);
}
- (BOOL)isPendingApproval
{
// Either of the following mean we're waiting to have our presence subscription approved:
// <item ask='subscribe' subscription='none' jid='robbiehanson#deusty.com'/>
// <item ask='subscribe' subscription='from' jid='robbiehanson#deusty.com'/>
NSString *subscription = self.subscription;
NSString *ask = self.ask;
if ([subscription isEqualToString:#"none"] || [subscription isEqualToString:#"from"])
{
if ([ask isEqualToString:#"subscribe"])
{
return YES;
}
}
return NO;
}
- (id <XMPPResource>)resourceForJID:(XMPPJID *)jid
{
NSString *jidStr = [jid full];
for (XMPPResourceCoreDataStorageObject *resource in [self resources])
{
if ([jidStr isEqualToString:[resource jidStr]])
{
return resource;
}
}
return nil;
}
- (NSArray *)allResources
{
NSMutableArray *allResources = [NSMutableArray array];
for (XMPPResourceCoreDataStorageObject *resource in [[self resources] allObjects]) {
if(![resource isDeleted])
{
[allResources addObject:resource];
}
}
return allResources;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Comparisons
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Returns the result of invoking compareByName:options: with no options.
**/
- (NSComparisonResult)compareByName:(XMPPUserCoreDataStorageObject *)another
{
return [self compareByName:another options:0];
}
/**
* This method compares the two users according to their display name.
*
* Options for the search — you can combine any of the following using a C bitwise OR operator:
* NSCaseInsensitiveSearch, NSLiteralSearch, NSNumericSearch.
* See "String Programming Guide for Cocoa" for details on these options.
**/
- (NSComparisonResult)compareByName:(XMPPUserCoreDataStorageObject *)another options:(NSStringCompareOptions)mask
{
NSString *myName = [self displayName];
NSString *theirName = [another displayName];
return [myName compare:theirName options:mask];
}
/**
* Returns the result of invoking compareByAvailabilityName:options: with no options.
**/
- (NSComparisonResult)compareByAvailabilityName:(XMPPUserCoreDataStorageObject *)another
{
return [self compareByAvailabilityName:another options:0];
}
/**
* This method compares the two users according to availability first, and then display name.
* Thus available users come before unavailable users.
* If both users are available, or both users are not available,
* this method follows the same functionality as the compareByName:options: as documented above.
**/
- (NSComparisonResult)compareByAvailabilityName:(XMPPUserCoreDataStorageObject *)another
options:(NSStringCompareOptions)mask
{
if ([self isOnline])
{
if ([another isOnline])
return [self compareByName:another options:mask];
else
return NSOrderedAscending;
}
else
{
if ([another isOnline])
return NSOrderedDescending;
else
return [self compareByName:another options:mask];
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark KVO compliance methods
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ (NSSet *)keyPathsForValuesAffectingJid {
// If the jidStr changes, the jid may change as well.
return [NSSet setWithObject:#"jidStr"];
}
+ (NSSet *)keyPathsForValuesAffectingIsOnline {
return [NSSet setWithObject:#"primaryResource"];
}
+ (NSSet *)keyPathsForValuesAffectingSection {
// If the value of sectionNum changes, the section may change as well.
return [NSSet setWithObject:#"sectionNum"];
}
+ (NSSet *)keyPathsForValuesAffectingSectionName {
// If the value of displayName changes, the sectionName may change as well.
return [NSSet setWithObject:#"displayName"];
}
+ (NSSet *)keyPathsForValuesAffectingAllResources {
return [NSSet setWithObject:#"resources"];
}
#end
- (NSManagedObjectContext *)managedObjectContext_roster
{
return [xmppRosterStorage mainThreadManagedObjectContext];
}
- (NSManagedObjectContext *)mainThreadManagedObjectContext
{
NSAssert([NSThread isMainThread], #"Context reserved for main thread only");
if (mainThreadManagedObjectContext)
{
return mainThreadManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator)
{
XMPPLogVerbose(#"%#: Creating mainThreadManagedObjectContext", [self class]);
if ([NSManagedObjectContext instancesRespondToSelector:#selector(initWithConcurrencyType:)])
mainThreadManagedObjectContext =
[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
else
mainThreadManagedObjectContext = [[NSManagedObjectContext alloc] init];
mainThreadManagedObjectContext.persistentStoreCoordinator = coordinator;
mainThreadManagedObjectContext.undoManager = nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
// Todo: If we knew that our private managedObjectContext was going to be the only one writing to the database,
// then a small optimization would be to use it as the object when registering above.
}
return mainThreadManagedObjectContext;
}
- (void)managedObjectContextDidSave:(NSNotification *)notification
{
NSManagedObjectContext *sender = (NSManagedObjectContext *)[notification object];
if ((sender != mainThreadManagedObjectContext) &&
(sender.persistentStoreCoordinator == mainThreadManagedObjectContext.persistentStoreCoordinator))
{
XMPPLogVerbose(#"%#: %# - Merging changes into mainThreadManagedObjectContext", THIS_FILE, THIS_METHOD);
dispatch_async(dispatch_get_main_queue(), ^{
[mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
[self mainThreadManagedObjectContextDidMergeChanges];
});
}
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
// This is a public method.
// It may be invoked on any thread/queue.
__block NSPersistentStoreCoordinator *result = nil;
dispatch_block_t block = ^{ #autoreleasepool {
if (persistentStoreCoordinator)
{
result = persistentStoreCoordinator;
return;
}
NSManagedObjectModel *mom = [self managedObjectModel];
if (mom == nil)
{
return;
}
XMPPLogVerbose(#"%#: Creating persistentStoreCoordinator", [self class]);
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
if (databaseFileName)
{
// SQLite persistent store
NSString *docsPath = [self persistentStoreDirectory];
NSString *storePath = [docsPath stringByAppendingPathComponent:databaseFileName];
if (storePath)
{
// If storePath is nil, then NSURL will throw an exception
if(autoRemovePreviousDatabaseFile)
{
if ([[NSFileManager defaultManager] fileExistsAtPath:storePath])
{
[[NSFileManager defaultManager] removeItemAtPath:storePath error:nil];
}
}
[self willCreatePersistentStoreWithPath:storePath options:storeOptions];
NSError *error = nil;
BOOL didAddPersistentStore = [self addPersistentStoreWithPath:storePath options:storeOptions error:&error];
if(autoRecreateDatabaseFile && !didAddPersistentStore)
{
[[NSFileManager defaultManager] removeItemAtPath:storePath error:NULL];
didAddPersistentStore = [self addPersistentStoreWithPath:storePath options:storeOptions error:&error];
}
if (!didAddPersistentStore)
{
[self didNotAddPersistentStoreWithPath:storePath options:storeOptions error:error];
}
}
else
{
XMPPLogWarn(#"%#: Error creating persistentStoreCoordinator - Nil persistentStoreDirectory",
[self class]);
}
}
else
{
// In-Memory persistent store
[self willCreatePersistentStoreWithPath:nil options:storeOptions];
NSError *error = nil;
if (![self addPersistentStoreWithPath:nil options:storeOptions error:&error])
{
[self didNotAddPersistentStoreWithPath:nil options:storeOptions error:error];
}
}
result = persistentStoreCoordinator;
}};
if (dispatch_get_specific(storageQueueTag))
block();
else
dispatch_sync(storageQueue, block);
return result;
}
error iam getting is
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'XMPPUserCoreDataStorageObject''
in my app I am using Core Data with store type NSSQLiteStoreType. Starting ios 8 sdk all relations of object not fetching from Core Data. Can anyone explain what is the difference with Core Data in ios 8 and how can I fix this issue?
Here is a code of my DataService:
-(id)init{
self = [super init];
if (self){
coreDataHelpersForDispatchQueues = [NSMutableDictionary dictionary];
contextsForQispatchQueues = [NSMutableDictionary dictionary];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"Name" withExtension:#"momd"]];
_persistentStoreCoordinator = [self createStoreCoordinatorWithDataModel:_managedObjectModel storeUrl:[NSURL fileURLWithPath:[self databaseLocationPath:#"Name.sqlite"]]];
self.coreDataHelper = self.coreDataHelperForCurrentDispatchQueue;
_managedObjectContext = self.coreDataHelper.moc;
_managedObjectContext.mergePolicy = NSOverwriteMergePolicy;
[self logCount];
}
return self;
}
-(void)logCount{
#synchronized(coreDataHelpersForDispatchQueues){
//NSLog(#"count|%d|",coreDataHelpersForDispatchQueues.count);
}
[self performSelector:#selector(logCount) withObject:nil afterDelay:1];
}
#pragma mark - currentCDH
-(CoreDataHelper*)coreDataHelperForCurrentDispatchQueue{
#synchronized(coreDataHelpersForDispatchQueues){
CoreDataHelper* helper = coreDataHelpersForDispatchQueues[dispatch_current_queue_id];
if (!helper){
helper = [[CoreDataHelper alloc] initWithContext:self.newManagedObjectContext];
helper.retainCounter = 1;
coreDataHelpersForDispatchQueues[dispatch_current_queue_id] = helper;
NSLog(#"new helper|%#| context|%#| queue|%s|",helper,helper.moc,dispatch_queue_get_label(dispatch_get_current_queue()));
}
return helper;
}
}
-(void)retainCoreDataHelper:(CoreDataHelper*)coreDataHelper_{
coreDataHelper_.retainCounter ++;
}
-(void)releaseCoreDataHelper:(CoreDataHelper *)coreDataHelper_ now:(BOOL)now_{
if (!coreDataHelper_ || (coreDataHelper_.moc == self.coreDataHelper.moc && !now_))
return;
coreDataHelper_.retainCounter --;
if (now_ || coreDataHelper_.retainCounter <= 0){
__block CoreDataHelper* helper = coreDataHelper_;
dispatch_block_t doit = ^{
NSLog(#"consuming helper|%#| context|%#| started",helper,helper.moc);
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:helper.moc];
#synchronized(contextsForQispatchQueues){
NSNumber* keyToRemove = nil;
for (NSNumber* key in contextsForQispatchQueues) {
if (contextsForQispatchQueues[key] == helper.moc){
keyToRemove = key;
break;
}
}
if (keyToRemove)
[contextsForQispatchQueues removeObjectForKey:keyToRemove];
}
#synchronized(coreDataHelpersForDispatchQueues){
NSNumber* keyToRemove = nil;
for (NSNumber* key in coreDataHelpersForDispatchQueues) {
if (coreDataHelpersForDispatchQueues[key] == coreDataHelper_){
keyToRemove = key;
break;
}
}
if (keyToRemove)
[coreDataHelpersForDispatchQueues removeObjectForKey:keyToRemove];
}
NSLog(#"consuming helper|%#| context|%#| finished",helper,helper.moc);
};
if (now_){
NSLog(#"will consume helper|%#| context|%#| queue|%s| just now",helper,helper.moc,dispatch_queue_get_label(dispatch_get_current_queue()));
doit();
}else{
int64_t delayInSeconds = 5.0;
NSLog(#"will consume helper|%#| context|%#| queue|%s| in %lld seconds",helper,helper.moc,dispatch_queue_get_label(dispatch_get_current_queue()),delayInSeconds);
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_global_queue(0, 0), doit);
}
}
}
-(NSManagedObjectContext*)newManagedObjectContext{
NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = self.persistentStoreCoordinator;
#synchronized(contextsForQispatchQueues){
contextsForQispatchQueues[dispatch_current_queue_id] = context;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleContextDidSaveNotification:) name: NSManagedObjectContextDidSaveNotification object:context];
return context;
}
-(void)handleContextDidSaveNotification:(NSNotification *)notification {
#synchronized(contextsForQispatchQueues){
NSManagedObjectContext* savedContext = notification.object;
for (NSManagedObjectContext* context in contextsForQispatchQueues.allValues) {
if (context != savedContext)
[context mergeChangesFromContextDidSaveNotification:notification];
}
}
}
#pragma mark -
-(NSPersistentStoreCoordinator*)createStoreCoordinatorWithDataModel:(NSManagedObjectModel*)model storeUrl:(NSURL*)url{
NSError *error = nil;
NSPersistentStoreCoordinator* cordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSDictionary *options = #{
NSSQLitePragmasOption: #{#"journal_mode": #"OFF"}
};
if (![cordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error]){
[[NSFileManager defaultManager] removeItemAtURL:url error:nil];
NSLog(#"database was purged: %#",url.absoluteString);
NSError* error2 = nil;
if (![cordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error2]) {
NSLog(#"Unresolved error %#, %#", error2, [error2 userInfo]);
abort();
}
}
return cordinator;
}
-(NSManagedObjectContext*)createManagedObjectContextForStoreCoordinator:(NSPersistentStoreCoordinator*)coordinator{
NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = coordinator;
// [[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleContextSavedNotification:) name:NSManagedObjectContextDidSaveNotification object:context];
return context;
}
#pragma mark - Core Data stack
-(NSString*)databaseLocationPath:(NSString*)databaseName{
NSArray* documentDirectoryFolderLocation = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[documentDirectoryFolderLocation objectAtIndex:0] stringByAppendingPathComponent:databaseName];
}
Update:
Here is a code how I fetch results:
NSFetchRequest* oldInstructionsRequest = [[NSFetchRequest alloc] initWithEntityName:#"Instruction"];
oldInstructionsRequest.predicate = [NSPredicate predicateWithFormat:#"isFromList == NO && isForUpload == NO"];
oldInstructions = [app.dataService.managedObjectContextCopy executeFetchRequest:oldInstructionsRequest error:nil];
<Instruction: 0x190fae40> (entity: Instruction; id: 0x190fa7b0 <x-coredata://BDC5225D-BD51-412B-A247-C0A66947EA74/Instruction/p1> ; data: {
author = Public;
color = "";
created = "2014-02-28 10:21:50 +0000";
estimation = 0;
evaluation = nil;
favourite = 0;
id = "100b1974-0cdd-4d94-a34f-caf3e2c0cc08";
imageId = 1955;
isForUpdate = 0;
isForUpload = 0;
isFromList = 1;
isNew = 0;
isRemoved = 0;
modified = "2014-04-18 16:33:55 +0000";
name = "Types of steps";
state = 4;
steps = "<relationship fault: 0x17f45ab0 'steps'>";
}),
Your approach to Core Data concurrency (using dispatch queues) it's not guaranteed to work. You can access objects from a NSManagedObjectContext only from a single thread, but a block scheduled on a dispatch queue can be executed on different threads.
Use performBlock: or performBlockAndWait: methods from NSManagedObjectContext. You won't need #synchronized statements at all if you do this.
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
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];