ios - resistant - tag heuer outlet
Datos principales: error: se detectó una excepción durante el procesamiento de cambio de datos centrales (3)
Bueno, todo el problema fue crear el NSManagedObjectContext
y todo en el Main Thread
y luego acceder a él o usarlo en el Background Thread
.
Entonces, acabo de seguir este post y ahora todo está funcionando perfectamente y sin problemas :)
Muchas gracias por los comentarios, realmente me puso en la dirección correcta y era totalmente lo que necesitaba para poder encontrar el problema.
¡Gracias!
En la AppDelegate.h
+ (NSManagedObjectContext *)mainQueueContext;
+ (NSManagedObjectContext *)privateQueueContext;
Luego, en mi AppDelegate.m
#pragma mark - Singleton Access
+ (NSManagedObjectContext *)mainQueueContext
{
return [self mainQueueContext];
}
+ (NSManagedObjectContext *)privateQueueContext
{
return [self privateQueueContext];
}
#pragma mark - Getters
- (NSManagedObjectContext *)mainQueueContext
{
if (!_mainQueueContext) {
_mainQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
}
return _mainQueueContext;
}
- (NSManagedObjectContext *)privateQueueContext
{
if (!_privateQueueContext) {
_privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_privateQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
}
return _privateQueueContext;
}
- (id)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSavePrivateQueueContext:)
name:NSManagedObjectContextDidSaveNotification
object:[self privateQueueContext]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSaveMainQueueContext:)
name:NSManagedObjectContextDidSaveNotification
object:[self mainQueueContext]];
}
return self;
}
#pragma mark - Notifications
- (void)contextDidSavePrivateQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.mainQueueContext performBlock:^{
[self.mainQueueContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}
- (void)contextDidSaveMainQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.privateQueueContext performBlock:^{
[self.privateQueueContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Y, finalmente, en mi ViewController, donde estoy enviando el trabajo al fondo ...
// dont forget the macro
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(kBgQueue, ^{
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate privateQueueContext];
// do something in the background with your managedObjectContext!!!!
});
He tenido este problema ahora por unos días y es realmente frustrante. He estado revisando mi código una y otra vez, he intentado algo diferente y sigo teniendo el mismo problema. Lo cual sucede solo el 50% de las veces, no siempre. Esto lo hace más difícil ...
El problema,
Estoy analizando los datos de 3 archivos csv a mi Core Data, que 2 de los archivos de análisis siempre van bien, pero el segundo / segundo archivo es donde siempre ocurre el bloqueo, así será la dirección de ese archivo y la clase managedObjectContext para este archivo .
Mensaje de error
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''
Entonces, en mi clase FetchData intento tratar el problema de diferentes maneras.
- Primero, cambié mi archivo .csv e inserté N / A en todos los campos / celdas que estaban vacíos.
- Segundo, estoy haciendo un chequeo en mi clase FetchData si esto no tiene ningún valor, guarde N / A.
- Tercero, en mi controlador de vista, donde estoy disparando el análisis sintáctico de los datos, ahora he separado tres propiedades diferentes para estas 3 entidades en mis datos centrales.
@property (no atómico, fuerte) NSManagedObjectContext * managedObjectContext;
@property (no atómico, fuerte) NSManagedObjectContext * managedObjectContextGI;
@property (no atómico, fuerte) NSManagedObjectContext * managedObjectContextVA;
Puede ser un poco loco o lo que sea, pero realmente necesito solucionarlo, por lo que intentar cualquier posible solución o enfoque a esto siempre es bueno, creo.
ViewController para llamar a las funciones para realizar el análisis ...
//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];
}
});
}
Estas son mis funciones de modelo de Datos de Core y así sucesivamente ... Lo cual he realizado el chequeo si estaba vacío, salvo N / A, y así sucesivamente ... todas mis propiedades que están en mi entidad son cadenas de caracteres
#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];
}
** ¡Aquí es donde ocurre el ahorro! *
#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];
}
Bueno, publiqué el código más relevante que pienso sobre el problema. Por favor, si se necesita algo más o más detalles sobre el problema, avíseme y se lo facilitaré.
¡Gracias por adelantado!
La línea de abajo salvó mi día:
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
Solo tiene que configurar el tipo de concurrencia como Privado. De esta forma, puede realizar múltiples operaciones en la base de datos al mismo tiempo en colas privadas.
Para las personas que lo están haciendo en Swift 3:
var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)