• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

iphone - NSFetchedResultsController 和插入记录的问题

[复制链接]
菜鸟教程小白 发表于 2022-12-13 06:40:03 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

好的,这个让我发疯了,我已经尝试了所有可以在互联网上找到的可能的解决方案,但仍然没有。所以这是我的情况: 我有一个 View ,上面有一个按钮。当它被触摸时,它会弹出一个客户列表供用户选择。当他们选择它时,我使用 fetchedresultscontroller 来获取与客户关联的部件并将它们显示在 tableview 中。这一切都很好。问题是如果我选择了客户 A 并插入一个新部件,然后转到客户 B 并插入一个新部件,当我重新选择客户 A 并尝试插入另一个部件时,应用程序崩溃并出现以下错误:

* Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UITableView.m:976 2011-02-21 10:39:12.896 SalesPro[36203:207] Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted). with userInfo (null) 2011-02-21 10:39:12.907 SalesPro[36203:207] * Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView scrollToRowAtIndexPath:atScrollPosition:animated:]: row (1) beyond bounds (1) for section (0).'

处理客户选择的代码

-(void) CustomerSelectedRaisedNSNotification *)notif
{
    NSLog(@"Received Notification - Customer Selected");
    selectedCustomer = (Customer *)[notif object];
    [self buildCustomerInfoText];
    if (popoverController != nil) {
        [popoverController dismissPopoverAnimated:YES];
    }

    fetchedResultsController = nil;

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        //Update to handle error appropriately
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1); //fail
    }

    [self.partsListGrid reloadData];
}

FetchedResultsController 代码

#pragma mark -
#pragma mark Fetch results controller

- (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    //set-up fetched results controller
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName"artsList" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setFetchBatchSize:20];
    NSLog(@"TAMS ID: %@", selectedCustomer.customerTAMSID);
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat"customerTAMSID == %@", selectedCustomer.customerTAMSID]]; 

    //set to sort by customer name
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey"sortOrder" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];   
    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] 
                                                             initWithFetchRequest:fetchRequest 
                                                             managedObjectContext:[self managedObjectContext] 
                                                             sectionNameKeyPath:nil cacheName:nil];
    [aFetchedResultsController setDelegate:self];
    [self setFetchedResultsController:aFetchedResultsController];

    //clean-up
    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    //return results
    return fetchedResultsController;
}

- (void)controllerWillChangeContentNSFetchedResultsController*)controller 
{
    [[self partsListGrid] beginUpdates];
}

- (void)controllerDidChangeContentNSFetchedResultsController *)controller {
    // In the simplest, most efficient, case, reload the table view.
    [[self partsListGrid] endUpdates];
}

- (void)controllerNSFetchedResultsController *)controller didChangeObjectid)anObject
       atIndexPathNSIndexPath *)indexPath forChangeTypeNSFetchedResultsChangeType)type
      newIndexPathNSIndexPath *)newIndexPath {

    UITableView *tableView = self.partsListGrid;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath withHeight:tableView.rowHeight];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controllerNSFetchedResultsController *)controller didChangeSectionid <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.partsListGrid insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [self.partsListGrid deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeMove:
            break;
        case NSFetchedResultsChangeUpdate: 
            break;
        default:
            break;
    }
}

添加零件代码

-(void) addScannedPart:(Part *)part 
{
    // Check to see if entered part is already in list
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *partsEntity = [NSEntityDescription entityForName"artsList" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:partsEntity];

    NSPredicate *predicate = [NSPredicate predicateWithFormat: @"customerTAMSID == %@ AND lineAbbreviation == %@ AND partNumber == %@", selectedCustomer.customerTAMSID, part.lineAbbrev, part.partNumber];
    [fetchRequest setPredicate:predicate];

    NSError *error = nil;
    NSArray *fetchedParts = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

    if ([fetchedParts count] == 0) {
        //Create a new instance of the entity managed object by the fetched results controller
        NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
        NSEntityDescription *entity = [[fetchedResultsController fetchRequest] entity];

        NSLog(@"Entity Name: %@", [entity name]);

        NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

        //Add fields to Managed Object
        int sortOrder = [[fetchedResultsController fetchedObjects] count];
        sortOrder++;

        [newManagedObject setValue:[part lineAbbrev] forKey"lineAbbreviation"];
        [newManagedObject setValue:[part partNumber] forKey"partNumber"];
        [newManagedObject setValue:[NSNumber numberWithInt:[[part orderQty] intValue]] forKey"orderQuantity"];
        [newManagedObject setValue:selectedCustomer.customerTAMSID forKey"customerTAMSID"];
        [newManagedObject setValue:[NSNumber numberWithInt:sortOrder] forKey"sortOrder"];

        //Save the context
        NSError *error = nil;
        if (![context save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }

        //reload Customer list 
        NSIndexPath *insertionPath = [fetchedResultsController indexPathForObject:newManagedObject];
        [self.partsListGrid selectRowAtIndexPath:insertionPath animated:YES scrollPosition:UITableViewScrollPositionTop];
        [self.partsListGrid reloadData];
    }
}

这是我必须为我们的下一个版本(很快)解决的最大(最严重)缺陷。我将不胜感激任何帮助!谢谢!



Best Answer-推荐答案


从修复泄漏的 NSFetchedResultsCONtroller 开始

-(void) CustomerSelectedRaised:(NSNotification *)notif
{
    /*...*/
    fetchedResultsController = nil;
    /*...*/
}

你不应该有多个 NSFetchedResultsControllers 都报告对同一个 tableview 的更改。我认为这就是正在发生的事情。除非 NSFRController 被释放,否则它将向其委托(delegate)报告更改

关于iphone - NSFetchedResultsController 和插入记录的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5068511/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap