【问题标题】:How can I insert new objects at top of UITableView backed by Core Data/NSFetchedResultsController?如何在 Core Data/NSFetchedResultsController 支持的 UITableView 顶部插入新对象?
【发布时间】:2010-08-03 02:24:29
【问题描述】:

我有一个成功合并 NSFetchedResultsController 的 tableview。但是,我需要在我的 tableview 中最顶层的单元格读取“添加新对象”并使用 UITableViewCellEditingStyleInsert 而不是默认的 UITableViewCellEditingStyleDelete。

FetchResultsController 想要检查 managedObjectContext 中的对象——既要确定行数又要填充表格单元格。我能想到解决这个问题的唯一方法是创建一个虚拟对象,但我觉得应该有一个更优雅的解决方案。

更新:

对于那些可能对我最终得到什么解决方案感到好奇的人,我决定将插入单元格放在底部,而不是顶部。以下是相关代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    //self.clearsSelectionOnViewWillAppear = NO;

    self.editing = YES;
    self.tableView.allowsSelectionDuringEditing = YES;
    self.tableView.delegate = self;

    RubricAppDelegate *appDelegate = (RubricAppDelegate *)[[UIApplication sharedApplication] delegate];
    managedObjectContext = [appDelegate managedObjectContext];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"myClass" inManagedObjectContext:managedObjectContext];
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    [request setEntity:entity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"classID" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptor release];

    fetchedResultsController = [[NSFetchedResultsController alloc]
                                               initWithFetchRequest:request 
                                               managedObjectContext:self.managedObjectContext
                                               sectionNameKeyPath:nil cacheName:nil];
    NSError *error;
    [fetchedResultsController performFetch:&error];

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    NSLog(@"Number of sections = %d", [[fetchedResultsController sections] count]);

    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    id <NSFetchedResultsSectionInfo> myClass = [[fetchedResultsController sections] objectAtIndex:section];
    NSLog(@"Number of classes = %d", [myClass numberOfObjects]);

    return ([[fetchedResultsController fetchedObjects] count] + 1);

}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    NSLog(@"FRC count + 1 = %d", ([[fetchedResultsController fetchedObjects] count] + 1));

    if (indexPath.row == ([[fetchedResultsController fetchedObjects] count])) {
        cell.textLabel.text = @"Add New Class";
    }
    else {
        myClass *theClass = [fetchedResultsController objectAtIndexPath:indexPath];
        NSLog(@"Class name is: %@", theClass.classTitle);
        cell.textLabel.text = theClass.classTitle;
    }


    return cell;
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == [[fetchedResultsController fetchedObjects] count]) {
        return UITableViewCellEditingStyleInsert;
    }
    return UITableViewCellEditingStyleDelete;
}

结果(带有一些垃圾数据):

现在我唯一的问题是让删除功能正常工作。你可以关注我在那个问题上的帖子here

【问题讨论】:

    标签: core-data uitableview


    【解决方案1】:

    通常添加行在底部。

    您可以通过更改 -tableView:numberOfRowsInSection:-tableView:cellForRowAtIndexPath: 方法来调整单元格计数并进行调整来实现此目的。因此,您的 -tableView:numberOfRowsInSection: 将返回 N+1,而您的 -tableView:cellForRowAtIndexPath: 将在 N-1 处获取对象,除非 N == 0,否则它将返回您的“添加新对象”单元格。

    没有必要弄乱底层的 Core Data 元素,因为这完全是一个 UI 问题。

    更新

    但现在我不确定如何返回我获取的对象的计数(假设这是我在您上面的答案中用于“N”的)。另外,当 indexPath.row = (N + 1) 而不是 N = 0 时,我不希望 -tableView:cellForRowAtIndexPath 返回我的“添加新对象”单元格吗?我可能误解了“N”的含义,但我认为它只是意味着获取对象的数量。

    是的,它是实际对象的计数。

    您确实希望您的-tableView:cellForRowAtIndexPath: 为您的“添加新对象”返回一个单元格,否则有什么意义?您只希望它返回 不同 类型的单元格。

    您在此解决方案中所做的只是添加一个不属于NSFetchedResultsController 的单元格,然后在您从NSFetchedResultsController 检索实际对象以及用户选择一个单元格时对其进行补偿。

    【讨论】:

    • 这可能值得另一篇文章,但是关于 NSFetchedResultsController 的一个奇怪的事情(至少在我设置的时候)是每个对象都在其自己的部分中返回。如果只有一个部分并且每个对象都分配到不同的行,我会更喜欢它,但是如果我将 -numberOfSectionsInTableView 设置为返回 1,它只会显示一个对象并删除其余对象。鉴于这一事实,我尝试为我的部分返回 N+1,为对象检索返回 N-1,但仍然不行。
    • 为此创建一个新帖子并显示您的代码。听起来您的控制器配置或数据源委托方法中有问题。
    • Marcus,如果我的声誉足够高,我会支持您的回答:P 在发布另一个问题后,我将部分设置为 1,并且我的对象返回到该部分的行。我没有将 sectionNameKeyPath 设置为 nil。但是现在我不确定如何返回我获取的对象的计数(假设这是我在上面的答案中用于“N”的)。另外,当 indexPath.row = (N + 1) 而不是 N = 0 时,我不希望 -tableView:cellForRowAtIndexPath 返回我的“添加新对象”单元格吗?我可能误解了“N”的含义,但我认为它只是意味着获取对象的数量。
    • 对于吸收速度如此缓慢,我深表歉意。我尚未将您的回复标记为答案,因为我还无法验证它是否有效。好吧,在我第 5 次或第 6 次查看代码之后,我发现我在实现它时出错了,它现在可以工作了!对于像我这样的初学者来说,这是一个小小的胜利:P 但是在寻找答案的过程中,我遇到了一个解决方案,它将插入单元格设置为 tableFooterView,从而消除了弄乱 FRC(在 cellForRowAtIndexPath 中)的需要。您会出于任何原因反对这样做吗?
    • 我个人更喜欢它,因为它可以生成更简洁的代码。如果你想放在顶部,你也可以把它放在标题中。
    猜你喜欢
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多