使用NSFetchedResultsController在空表上定制单元格 [英] Custom cell on empty table with NSFetchedResultsController

查看:137
本文介绍了使用NSFetchedResultsController在空表上定制单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在我的UITableView为空时放置一个自定义空单元格。



我使用以下代码:

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

int count = fetchedResultsController fetchedObjects] .count;
if(count == 0){
return 1;
}
return count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = nil;
int count = [self.fetchedResultsController fetchedObjects] .count;
if(count == 0){
//返回空单元格
cell = [self getEmptyCellOfTableView:tableView cellForRowAtIndexPath:indexPath];
} else {
cell = [self getMyQuestionCellOfTableView:tableView cellForRowAtIndexPath:indexPath];
}
return cell;
}

FRC didChangeObject 实施:

   - (void)controller:(NSFetchedResultsController *)controller 
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *) indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if(!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
{
switch )
{
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break

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

case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break

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

fetchedObject.count> 0 ,我得到以下错误:

  CoreData:error:严重应用程序错误。 
在调用 -
期间从NSFetchedResultsController的委托捕获到异常controllerDidChangeContent:无效的更新:部分0中的行数无效。
包含在现有段中的行数update(1)
必须等于更新前该节中包含的行数(1),
加或减从该节插入或删除的行数(插入1行,删除0行)
,加上或减去移入或移出该段的行数(移入0,移出0)。
with userInfo(null)



我理解这是因为我插入了1个新行



如何修复它以适应我的行为? >解决方案

表视图更新后, numberOfRowsInSection 返回的值必须正好为
,与前一行数加上



在插入第一个对象的情况下, insertRowsAtIndexPaths 在新对象的FRC委托方法中被调用,但是不是显示附加行,而是将空
单元格替换为另一个单元格,因此,



如果修改FRC委托方法,它应该会工作
controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
如下:

  case NSFetchedResultsChangeInsert:
if .fetchedResultsController fetchedObjects] count] == 1){
//第一个对象插入,空单元格被对象单元格替换
[tableView reloadRowsAtIndexPaths:@ [newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
} else {
[tableView insertRowsAtIndexPaths:@ [newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
break;

case NSFetchedResultsChangeDelete:
if([[self.fetchedResultsController fetchedObjects] count] == 0){
//最后一个对象被删除,对象单元格 cell
[tableView reloadRowsAtIndexPaths:@ [indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else {
[tableview deleteRowsAtIndexPaths:@ [indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
break;


I'm trying to place a custom empty cell when my UITableView is empty.

I use the following code:

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

    int count = [self.fetchedResultsController fetchedObjects].count;
    if (count == 0) {
        return 1;
    }
    return count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell * cell = nil;
    int count = [self.fetchedResultsController fetchedObjects].count;
    if (count == 0) {
        // return empty cell
        cell = [self getEmptyCellOfTableView:tableView cellForRowAtIndexPath:indexPath];
    } else {
        cell = [self getMyQuestionCellOfTableView:tableView cellForRowAtIndexPath:indexPath];
    }
    return cell;
}

FRC didChangeObject implementation:

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{       
    if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
    {
        switch(type)
        {
            case NSFetchedResultsChangeInsert:
                [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;

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

            case NSFetchedResultsChangeUpdate:
                [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;

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

This works perfectly, the problam is when the fetchedObject.count > 0 than i get the following error:

CoreData: error: 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) 
and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). 
with userInfo (null)

I understand that this happens because I inserted 1 new row and the count stays at 1 instead of becoming 2.

How can i fix it to fit my behavior?

解决方案

After a table view update, the value returned by numberOfRowsInSection must exactly match the previous number of rows plus the number of inserted rows minus the number of deleted rows.

In your case, when the first object is inserted, insertRowsAtIndexPaths is called in the FRC delegate method for the new object, but instead of displaying an additional row, the "empty" cell is replaced with a different cell, so the number of rows is still one.

It should work if you modify the FRC delegate method controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: as follows:

case NSFetchedResultsChangeInsert:
    if ([[self.fetchedResultsController fetchedObjects] count] == 1) {
        // First object inserted, "empty cell" is replaced by "object cell"
        [tableView reloadRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else {
        [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    break;

case NSFetchedResultsChangeDelete:
    if ([[self.fetchedResultsController fetchedObjects] count] == 0) {
        // Last object removed, "object cell" is replaced by "empty cell"
        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else {
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    break;

这篇关于使用NSFetchedResultsController在空表上定制单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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