核心数据:错误:在核心数据更改处理期间捕获到异常 [英] Core Data: error: Exception was caught during Core Data change processing

查看:106
本文介绍了核心数据:错误:在核心数据更改处理期间捕获到异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在遇到这个问题已经有几天了,这真令人沮丧..我一直在反复检查我的代码,尝试了不同的事情,并一直遇到同样的问题..仅发生50%的情况不是总是.这会更难.

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..

问题

我正在将3个csv文件中的数据解析为我的Core Data,其中的2个文件解析总是很顺利,但是中间/第二个文件总是发生崩溃,因此,这将是该文件和managedObjectContext类的地址该文件.

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.

错误消息

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'

因此,在我的 FetchData 类中,我尝试以不同的方式解决该问题.

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

  • 首先,我更改了.csv文件,并将N/A插入所有为空的字段/单元格中.
  • 第二,如果我的 FetchData 类没有任何价值,请检查我的情况,保存N/A.
  • 第三,在要解析数据的视图控制器中,我现在为核心数据中的这三个实体分离了三个不同的属性.
  • 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.

@属性(非原子的,坚固的)NSManagedObjectContext * managedObjectContext;

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

@属性(非原子的,强的)NSManagedObjectContext * managedObjectContextGI;

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContextGI;

@属性(非原子的,强的)NSManagedObjectContext * managedObjectContextVA;

@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调用函数来执行解析.

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];

           }

       });
}

这是我的 Core Data 模型函数,等等.我已检查它是否为空,保存了 N/A 等.所有我实体中的属性是字符串

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..

提前谢谢!

推荐答案

好吧,整个问题是在Main Thread中创建NSManagedObjectContext和所有内容,然后在Background Thread中访问或使用它.

Well, the whole problem was creating the NSManagedObjectContext and everything in the Main Thread and then accessing it or using it in the Background Thread.

所以,我刚刚关注了 这篇文章 ,现在一切都在顺利进行:)

So, I have just followed this post and now everything is working perfectly and smooth :)

非常感谢您的意见,这确实使我朝着正确的方向前进,而这完全是我发现问题所需要的.

Thanks a lot for the comments it really put me in the right direction and it was totally what I needed to be able to find the problem..

谢谢!

在AppDelegate.h

+ (NSManagedObjectContext *)mainQueueContext;
+ (NSManagedObjectContext *)privateQueueContext;

然后,在我的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];
}

最后,在我的 ViewController 中,我将工作发送到后台.

And, finally in my ViewController where I am sending the work to the background..

// 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!!!!

 });

这篇关于核心数据:错误:在核心数据更改处理期间捕获到异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆