Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data: error: Exception was caught during Core Data change processing

I have been having this problem now for a few days and it's really frustrating.. I have been reviewing my code over and over again tried different thing and keeps having the same issue.. Which happens only 50% of the times not always. This makes it harder..

The Problem,

I am parsing the data from 3 csv files to my Core Data, which 2 of the files parsing always goes well but the middle/second file is where the crash always happens so, this will be address to that file and managedObjectContext class for this file.

Error Message

CoreData: error: Serious application error.   Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.   -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null) 2014-09-12 11:27:06.115 AppName[210:3907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil' 

So, in my FetchData class I try to address the problem in different ways.

  • First, I changed my .csv file and insert N/A to all the fields/cells that were empty.
  • Second, I'm doing a check in my FetchData class if this doesn't has any value, save N/A.
  • Third, In my view controller where I'm firing the parsing the data, I have now separated three different properties for these 3 entities in my Core Data.

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContextGI;

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContextVA;

It might be a bit crazy or whatever but I really need to fix this so, trying any possible solution or approach to this it's always good, I think.

ViewController to calling the functions to perform the parsing..

//at the beginning of my model #define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)  -(IBAction)myLoadingTask:(id)sender{         dispatch_async(kBgQueue, ^{             NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];             NSString *savedValue = @"";             if([[userDefaults stringForKey:@"dataFetched"] length] > 0){                                            savedValue = [userDefaults stringForKey:@"dataFetched"];            }             // if the csv files data hasn't been fetch it, then fetch it            if([savedValue length] == 0){                 FetchData *fd = [[FetchData alloc] initWithManagedContext:self.managedObjectContext];                 // fetching benefits data                [fd beginParser];                 FetchGIBillData *fdGI = [[FetchGIBillData alloc] initWithManagedContext:self.managedObjectContextGI];                 // fetching gi bill data                [fdGI beginParser];                 FetchVAPhones *fdVA = [[FetchVAPhones alloc] initWithManagedContext:self.managedObjectContextVA];                 // fetching va phones                [fdVA beginParser];                 NSString *valueToSave = @"saved";                [[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:@"dataFetched"];                [[NSUserDefaults standardUserDefaults] synchronize];             }         }); } 

This is my Core Data model functions and so on.. Which I have performed the check if it was empty save N/A and so on.. all my properties which are in my entity are strings

#define GIBILL_FILENAME @"gi_bill_data"  int numOfEntries; - (id)initWithManagedContext:(NSManagedObjectContext*)managedObjectContext {     self.managedObjectContext = managedObjectContext;     arrayOfRecords = [[NSMutableArray alloc] init];     numOfEntries=0;     return self; }   - (void) beginParser {     if (self.managedObjectContext == nil){         // Error: Must pass in NSManagedObjectContext         return;     }      NSString *filePath = [[NSBundle mainBundle] pathForResource:GIBILL_FILENAME ofType:@"csv"];     NSInputStream *stream = [NSInputStream inputStreamWithFileAtPath:filePath];     NSStringEncoding encoding = NSUTF8StringEncoding;//NSWindowsCP1250StringEncoding;      CHCSVParser *parser = [[CHCSVParser alloc] initWithInputStream:stream usedEncoding:&encoding delimiter:','];     parser.delegate = self;      [parser parse];      // uncomment to update data x amount of dates     //[self checkDateForRefreshCSV:parser];  } 

** This is where the saving happens!! *

#pragma mark - Data Add /**  * addRows  * @param parser: the CHCSV parser that will parse if required refresh  * @brief: add the row to ths managedObjectContent DB. All values saved.  */ - (void) addRows:(CHCSVParser *)parser {     int i = -1;     if ([arrayOfRecords count] == 0) return;     GIBill *data = [NSEntityDescription                       insertNewObjectForEntityForName:@"GIBill"                       inManagedObjectContext:self.managedObjectContext];      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.facility_code = [arrayOfRecords objectAtIndex:i];     else         data.facility_code = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.institution = [arrayOfRecords objectAtIndex:i];     else         data.institution = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.city = [arrayOfRecords objectAtIndex:i];     else         data.city = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.state = [arrayOfRecords objectAtIndex:i];     else         data.state = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.country = [arrayOfRecords objectAtIndex:i];     else         data.country = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.bah = [arrayOfRecords objectAtIndex:i];     else         data.bah = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.poe = [arrayOfRecords objectAtIndex:i];     else         data.poe = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.yr = [arrayOfRecords objectAtIndex:i];     else         data.yr = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.gibill = [arrayOfRecords objectAtIndex:i];     else         data.gibill = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 0)         data.cross = [arrayOfRecords objectAtIndex:i];     else         data.cross = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.grad_rate = [arrayOfRecords objectAtIndex:i];     else         data.grad_rate = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.grad_rate_rank = [arrayOfRecords objectAtIndex:i];     else         data.grad_rate_rank = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.default_rate = [arrayOfRecords objectAtIndex:i];     else         data.default_rate = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.avg_stu_loan_debt = [arrayOfRecords objectAtIndex:i];     else         data.avg_stu_loan_debt = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.avg_stu_loan_debt_rank = [arrayOfRecords objectAtIndex:i];     else         data.avg_stu_loan_debt_rank = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.indicator_group = [arrayOfRecords objectAtIndex:i];     else         data.indicator_group = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.salary = [arrayOfRecords objectAtIndex:i];     else         data.salary = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.zip = [arrayOfRecords objectAtIndex:i];     else         data.zip = @"N/A";      if([[arrayOfRecords objectAtIndex:++i] length] > 2)         data.ope = [arrayOfRecords objectAtIndex:i];     else         data.ope = @"N/A";      NSError *error;      [self.managedObjectContext save:&error];  } 

Well, I posted the most relevant code that I think of the issue. Please if something else is needed or more details about the problem let me know and I will provide it..

Thanks in advance!

like image 990
valbu17 Avatar asked Sep 12 '14 15:09

valbu17


1 Answers

The line below saved my day:

_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

You just have to set the concurrency type as Private. This way it can perform multiple operations on database concurrently on private queue's.

like image 174
Mohit Manhas Avatar answered Sep 21 '22 00:09

Mohit Manhas