UItableView上的多个NsfetchedResultsController

时间:2010-09-03 14:00:44

标签: iphone uitableview nsmutablearray nsfetchedresultscontroller

我在nsfetchedresultsController中实施2 tableView时遇到了困难。我想在表的每个部分(2个部分)中使用fetchedresultsController,如下所示:

收藏

  • 产品
  • 产品2


  • 产品3

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

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

  

无效更新:第0部分中的行数无效   更新(0)后必须包含在现有部分中的行   等于之前该部分中包含的行数   update(0),加上或减去插入或删除的行数   该部分(1个插入,0个删除)。 with 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;
    }
}   
}

4 个答案:

答案 0 :(得分:4)

查看Stack Overflow上的其他问题:


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

Core Data: UITableView with multiple NSFetchedResultControllers

答案 1 :(得分:2)

使用multiple是错误的方法。正确的解决方案是使用sectionNameKeyPath param到NSFetchedResultController将结果分组到多个部分,在您的情况下,它将是产品上购买的布尔属性。而且你也应该按升序将它作为第一个排序描述符,因为你想购买上面未购买的。使用标题标题表委托方法返回字符串" Wishlist"和"已购买"对于每个部分索引。

如果您认为将来可能会有第3个列表,那么您最好使用数字状态属性,并在代码中为产品可以使用的每个状态(或列表)创建枚举。通常是如何做到这一点,而不是在布尔上排序。

答案 2 :(得分:1)

:)抱歉伙计这是一个noob错误..错误发生了,因为indexPath.section返回了tableView中的部分,但我在fetchedResultsController中没有任何部分(总是索引0)。编辑:实际上有一个..

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

不确定这是否是解决问题的最佳方法 THKS!
里卡多卡斯特罗

答案 3 :(得分:1)

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

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