【问题标题】:Multiple NsfetchedResultsController on a UItableViewUItableView 上的多个 NsfetchedResultsController
【发布时间】:2010-09-03 14:00:43
【问题描述】:

我很难在 tableView 中实现 2 nsfetchedresultsController。我想在表的每个部分(2 个部分)中都有一个 fetchedresultsController,如下所示:

愿望清单

  • 产品
  • 产品2

已购买

  • 产品3

我知道对于这个例子我不需要 2 个 nsfetchedResultsController 但我稍后会需要这个..

当我从一个 nsfetchedResultsController 中删除一个产品时,它会传递给另一个,我得到这个错误:

无效更新:第 0 节中的行数无效。 更新 (0) 后包含在现有节中的行必须是 等于该节之前包含的行数 update (0),加上或减去插入或删除的行数 该部分(插入 1 个,删除 0 个)。与 userInfo (null)"

我认为这是因为当第一个 fetchedRController 检测到更改时,它会在调用第二个之前更新 tableView 对吗?我应该使用 NSMutableArrays 并手动更新 tableView 吗?

代码:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
NSInteger numberOfRows = 0;

switch (section)
{
    case WISHLIST_SECTION:

    {
        numberOfRows =[[fetchedResultsControllerwish fetchedObjects]count];


    };
         break;

    case PURCHASED_SECTION:
    {   
        numberOfRows =[[fetchedResultsControllerPurchased fetchedObjects]count];

    };
        break;


    default:
        break;
}
return numberOfRows;
}

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{

// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}

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

UITableView *tableViewT = self.tableView;

switch(type) {

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

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

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(GiftEventTableViewCell *)[tableViewT cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;

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

-(void)configureCell:(GiftEventTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.section) {
    case WISHLIST_SECTION:
    {
        GiftEvent *giftEv=(GiftEvent *)[fetchedResultsControllerwish objectAtIndexPath:indexPath];
        cell.gift=giftEv;

    };
        break;
    case PURCHASED_SECTION:
    {
        GiftEvent *giftEv=(GiftEvent *)[fetchedResultsControllerPurchased objectAtIndexPath:indexPath];

        //if i don't use indexpath.row in the second section i get an out of bounds error
        //GiftEvent *giftEv=(GiftEvent *)[[fetchedResultsControllerPurchased fetchedObjects]objectAtIndex: indexPath.row];
        cell.gift=giftEv;

    };
        break;




    default:
        break;
}

}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) 
{
    switch (indexPath.section) {
        case WISHLIST_SECTION:
        {
            // Delete the managed object for the given index path

            [self.managedObjectContext deleteObject:[fetchedResultsControllerwish objectAtIndexPath:indexPath]];

            // Save the context.
            NSError *error;
            if (![self.managedObjectContext save:&error]) {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                 */
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
            [self.tableView reloadData];

             };
            break;
        case PURCHASED_SECTION:
        {
            // Delete the managed object for the given index path

            [self.managedObjectContext deleteObject:[fetchedResultsControllerPurchased objectAtIndexPath:indexPath]];

            // Save the context.
            NSError *error;
            if (![self.managedObjectContext save:&error]) {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                 */
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }

        };
            break;

        default:
            break;
    }
}   
}

【问题讨论】:

    标签: iphone uitableview nsmutablearray nsfetchedresultscontroller


    【解决方案1】:

    查看 Stack Overflow 上的另一个问题:


    核心数据:具有多个 NSFetchedResultControllers 的 UITableView

    Core Data: UITableView with multiple NSFetchedResultControllers

    【讨论】:

      【解决方案2】:

      使用多个是错误的方法。正确的解决方案是使用 sectionNameKeyPath 参数到 NSFetchedResultController 将结果分组到多个部分,在您的情况下,它将是产品上购买的布尔属性。并且您还应该将其设为升序排列的第一个排序描述符,因为您希望在购买之上未购买。使用标题标题表委托方法返回每个部分索引的字符串“Wishlist”和“Purchased”。

      如果您认为将来可能有第三个列表,那么您最好使用数字状态属性,并在代码中为产品可能处于的每个状态(或列表)设置一个枚举。通常就是这样完成而不是在布尔上排序。

      【讨论】:

        【解决方案3】:

        我刚刚创建了一个 pod 来解决这个问题。 https://github.com/imton/GMCoreDataMultipleSectionsTableVC

        您可以查看并告诉我您的想法,欢迎反馈!

        G

        【讨论】:

          【解决方案4】:

          对不起,这是一个菜鸟错误。发生错误是因为 indexPath.section 返回了 tableView 中的部分,但我在 fetchedResultsController 中没有部分(总是索引 0)。

          编辑:实际上有一个..

          NSIndexPath *indexPathTemp = [NSIndexPath indexPathForRow:indexPath.row inSection:0];
          

          不确定这是否是最好的方法,但解决了问题。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-06
            • 1970-01-01
            相关资源
            最近更新 更多