无法保存核心数据

Posted

技术标签:

【中文标题】无法保存核心数据【英文标题】:Can't save Core Data 【发布时间】:2016-01-24 15:29:24 【问题描述】:

我尝试使用 NSFetchedResultsController 和不同部分将核心数据保存在 tableview 中。

当我添加数据时出现以下错误:

CoreData:错误:严重的应用程序错误。异常被捕获 在核心数据更改处理期间。这通常是一个错误 NSManagedObjectContextObjectsDidChangeNotification 的观察者。 * -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: 尝试使用 userInfo (null) 从 objects[0] 插入 nil 对象 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“ -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: 尝试插入 nil 对象 对象[0] *

第一次抛出调用堆栈:(0x181a05900 0x181073f80 0x1818f41a8 0x1818f4040 0x1000a9068 0x1000aa8d8 0x1835905a8 0x183505080 0x183504f48 0x183495108 0x1819aafc4 0x1819aa7e4 0x1819aa564 0x181a0fde4 0x1818eb0f4 0x1822dad2c 0x18349506c 0x1835098d0 0x18349378c 0x183492240 0x1000aa3a0 0x18672fe50 0x1868b34a4 0x18672fe50 0x18672fdcc 0x186717a88 0x186717bd4 0x18672f6e4 0x18672f314 0x186727e30 0x1866f84cc 0x1866f6794 0x1819bcefc 0x1819bc990 0x1819ba690 0x1818e9680 0x182df8088 0x186760d90 0x10004c23c 0x18148a8b8) libc++abi.dylib: 以未捕获的方式终止 NSException 类型的异常`

我的代码:

MyDetailData* MyDetail = [NSEntityDescription insertNewObjectForEntityForName:@"MyDetailData" inManagedObjectContext:self._privateObjectContext];
[MyDetail setKategorie: NSLocalizedString(@"Test", nil)];
NSError *error = nil;
if (![MyDetail.managedObjectContext save:&error]) 
      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

ios6 下,该代码一切正常

这是我的 NSFetchedResultsController

- (NSFetchedResultsController *)fetchedResultsController2 

    if (fetchedResultsController2 != nil) 
       return fetchedResultsController2;
    

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription     entityForName:@"MyDetailData" inManagedObjectContext:_privateObjectContext];
    [request setEntity:entity];

    NSSortDescriptor *KategorieDescriptor = [[NSSortDescriptor alloc] initWithKey:@"kategorie" ascending:YES];
    NSSortDescriptor *oderDescriptor = [[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES];
    NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:KategorieDescriptor,oderDescriptor,nameDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];


    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:_privateObjectContext sectionNameKeyPath:@"kategorie" cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController2 = aFetchedResultsController;

    return fetchedResultsController2;

  

TableView 委托

numberOfSectionsInTableView numberOfRowsInSection NSFetchedResultsController didChangeObject -> NSFetchedResultsChangeInsert NSFetchedResultsController didChangeSection -> NSFetchedResultsChangeInsert

调用并包含正确的信息 - 这是相关代码:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return [[fetchedResultsController2 sections] count];



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController2 sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];



- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath 

    if (userDrivenDataModelChange) return;

    switch(type) 
        case NSFetchedResultsChangeInsert:
            [self.tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate: 
            [self configureCell:[self.tv cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];

            NSString *sectionKeyPath = [controller sectionNameKeyPath];
            if (sectionKeyPath == nil)
                break;

            NSManagedObject *changedObject = [controller objectAtIndexPath:indexPath];
            NSArray *keyParts = [sectionKeyPath componentsSeparatedByString:@"."];
            id currentKeyValue = [changedObject valueForKeyPath:sectionKeyPath];
            for (int i = 0; i < [keyParts count] - 1; i++) 
                NSString *onePart = [keyParts objectAtIndex:i];
                changedObject = [changedObject valueForKey:onePart];
            
            sectionKeyPath = [keyParts lastObject];
            NSDictionary *committedValues = [changedObject committedValuesForKeys:nil];

            if ([[committedValues valueForKeyPath:sectionKeyPath] isEqual:currentKeyValue])
                break;

            NSUInteger tableSectionCount = [self.tv numberOfSections];
            NSUInteger frcSectionCount = [[controller sections] count];
            if (tableSectionCount != frcSectionCount) 
                // Need to insert a section
                NSArray *mysections = controller.sections;
                NSInteger newSectionLocation = -1;
                for (id oneSection in mysections) 
                    NSString *sectionName = [oneSection name];
                    if ([currentKeyValue isEqual:sectionName]) 
                        newSectionLocation = [mysections indexOfObject:oneSection];
                        break;
                    
                
                if (newSectionLocation == -1)
                    return; // uh oh

                if (!((newSectionLocation == 0) && (tableSectionCount == 1) && ([self.tv numberOfRowsInSection:0] == 0)))
                    [self.tv insertSections:[NSIndexSet indexSetWithIndex:newSectionLocation] withRowAnimation:UITableViewRowAnimationFade];
                NSUInteger indices[2] = newSectionLocation, 0;
                newIndexPath = [[NSIndexPath alloc] initWithIndexes:indices length:2];
            


        

        case NSFetchedResultsChangeMove:
            [self.tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:NO];
            [self.tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:NO];
            break;
        default:
            break;
    



- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type 
    switch(type) 

        case NSFetchedResultsChangeInsert:
            if (!((sectionIndex == 0) && ([self.tv numberOfSections] == 1)))
                [self.tv insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            if (!((sectionIndex == 0) && ([self.tv numberOfSections] == 1) ))
                [self.tv deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeMove:
            break;
        case NSFetchedResultsChangeUpdate: 
            break;
        default:
            break;
    

想法出了什么问题?

【问题讨论】:

能否添加请求代码 关键信息是[__NSPlaceholderDictionary ... init ... attempt to insert nil object from objects[0] @vadian 应该是什么意思。 某处尝试使用不允许的nil 对象初始化字典。 @BEN MESSAOUD Mahmoud 我给你的相关代码 【参考方案1】:

问题解决了。 在

didChangeObject

 case NSFetchedResultsChangeMove

我换行了

 [self.tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:NO];

  [self.tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                           withRowAnimation:NO];

   if (indexPath && newIndexPath) 
                 [self.tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:NO];

                 [self.tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                           withRowAnimation:NO];
   else 
                 NSLog(@"A table item was moved");
  

【讨论】:

以上是关于无法保存核心数据的主要内容,如果未能解决你的问题,请参考以下文章

无法将值保存到核心数据

核心数据 MOC 保存暂停执行并且无法保存(无错误或崩溃)

无法识别的选择器 - 保存到核心数据

核心数据无法保存 NSManagedObjectContext

无法将自定义对象从 API 保存到核心数据

设备密码锁定时无法保存核心数据托管对象上下文