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.
@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!
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With