为什么我不能删除我的UITableView的底行? [英] Why Can't I delete the bottom row of my UITableView?

查看:151
本文介绍了为什么我不能删除我的UITableView的底行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当用户按Edit时,UITableView在顶部添加一个插入行(绿色加号),并将所有其他行放入删除模式(红色减号)。或者,用户可以在不按压编辑按钮的情况下滑动到删除。我使用几个Ivars通过滑动或按下编辑按钮来跟踪表是否处于编辑模式,并相应地执行(例如,更新numberOfRowsInTableView:按下编辑时额外的插入行)。



一切都完美的除了在事情:当在编辑模式(即用户已明确地击中编辑按钮,并且插入行已经出现在顶部),如果用户尝试删除底行,下一行将被删除。删除任何其他行很好。



编辑 - 会显示以删除上面的行,但如果我立即退出并重新加载应用程序,它结果是底行已经走了。所以我猜测我的UITableView与NSFetchedResultsController不同步了。



这里是我使用的代码:

  #importChecklistsViewController.h
#importChecklist.h

@interface ChecklistsViewController(private)
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
- (void)addingView;
@end


@implementation ChecklistsViewController

@synthesize类别,managedObjectContext,fetchedResultsController;


- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if(self){
editingFromSwipe = NO;
tableIsEditing = NO;
}
return self;
}

- (void)dealloc
{
[category release];
[managedObjectContext release];
[fetchedResultsController release];
[super dealloc]
}

#pragma mark - 查看生命周期

- (void)viewDidLoad
{
[super viewDidLoad];
editingFromSwipe = NO;
tableIsEditing = NO;
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.tableView.allowsSelectionDuringEditing = YES;
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//对于支持的方向返回YES
return(interfaceOrientation == UIInterfaceOrientationPortrait);
}


#pragma mark - 表视图数据源

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id< NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
int rows = [sectionInfo numberOfObjects];

if(self.editing){
if(!editingFromSwipe&& tableIsEditing){
return rows +1;
}
return rows;
}
tableIsEditing = NO;
return rows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * CellIdentifier = @Cell ;

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

//配置单元格...
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;


NSLog(@should into into if statement here!\\\
);

if(tableView.editing){//
if((indexPath.row == 0)&&(!editingFromSwipe)){
NSLog编辑时添加按钮单元格\\\
);
cell.textLabel.text = @添加新清单;
cell.detailTextLabel.text = nil;
}
else {
NSLog(@编辑时配置其他单元格\ n);
[self configureCell:cell atIndexPath:indexPath];
}

}
else {
NSLog(@通常不编辑时配置单元\ n);
[self configureCell:cell atIndexPath:indexPath];
}


return cell;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(editingStyle = = UITableViewCellEditingStyleDelete)
{
//删除给定索引路径的管理对象
NSManagedObjectContext * context = [self.fetchedResultsController managedObjectContext];

int numberOfRows = [self tableView:tableView numberOfRowsInSection:indexPath.section];
int rowBeingDeleted = indexPath.row +1;

if(tableIsEditing&&!editingFromSwipe&& amp; numberOfRows == rowBeingDeleted){
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section]]];
}
else {
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
}

//保存上下文。
NSError * error = nil;
if(![context save:& error])
{
// TO DO:修复错误代码。
NSLog(@未解析的错误%@,%@,错误,[错误userInfo]);
abort();
}
}
else if(editingStyle == UITableViewCellEditingStyleInsert){
[self addingView];
}
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
int row = indexPath.row;

if(self.editing&& row == 0){
if(!editingFromSwipe&& tableIsEditing){
return UITableViewCellEditingStyleInsert;
}
else if(editingFromSwipe){
return UITableViewCellEditingStyleDelete;
}

}
return UITableViewCellEditingStyleDelete;
}


- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
editingFromSwipe = YES;
[super tableView:tableView willBeginEditingRowAtIndexPath:indexPath];
}

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
[super tableView:tableView didEndEditingRowAtIndexPath:indexPath];
editingFromSwipe = NO;
}


- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated ];

NSArray * addRow = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:0 inSection:0],nil];
[self.tableView beginUpdates];

if(!editingFromSwipe){
if(editing){
tableIsEditing = YES;
[self.tableView insertRowsAtIndexPaths:addRow withRowAnimation:UITableViewRowAnimationLeft];
}
else {
[self.tableView deleteRowsAtIndexPaths:addRow withRowAnimation:UITableViewRowAnimationLeft];
}
}
[self.tableView endUpdates];
}


#pragma mark - 表视图委托

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row!= 0){
TO DO:选择行时的代码
}
}


#pragma mark - Data


- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
清单* aChecklist = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = aChecklist.name;
cell.detailTextLabel.text = aChecklist.category.name;
}


- (void)addingView //:(id)sender
{
AddingViewController * viewController = [[AddingViewController alloc] initWithNibName:@ AddingViewControllerbundle:nil];

viewController.delegate = self;
viewController.title = @添加清单;

//创建导航控制器并以模态方式呈现
UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[self presentModalViewController:navigationController animated:YES];

viewController.textLabel.text = @输入新清单名称;

[navigationController release];
[viewController release];
}


#pragma mark - AddingViewDelegate


- (void)addingViewController:(AddingViewController *)addsViewController didAdd:(NSString * )itemAdded
{
if(itemAdded!= nil){

//关闭编辑模式。
if(self.editing)[self.navigationController setEditing:NO animated:NO];

//将类别名称添加到我们的模型和表视图中。

//创建由提取结果控制器管理的实体的新实例。
NSManagedObjectContext * context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription * entity = [[self.fetchedResultsController fetchRequest] entity];
清单* newChecklist = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

[category addChecklistsObject:newChecklist];

newChecklist.name = itemAdded;
// [newChecklist setDateStamp:[NSDate date]];

//保存上下文。
NSError * error = nil;
if(![context save:& error])
{
TO DO:修复错误代码。
NSLog(@未解析的错误%@,%@,错误,[错误userInfo]);
abort();
}


}

[self dismissModalViewControllerAnimated:YES];
}


#pragma mark - 获取结果控制器

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

//设置获取的结果控制器。

//为实体创建获取请求。
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
//根据需要编辑实体名称。
NSEntityDescription * entity = [NSEntityDescription entityForName:@ChecklistinManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
//设置4 *谓词,因此我们只看到此类别的检查表。
NSPredicate * requestPredicate = [NSPredicate predicateWithFormat:@category.name =%@,self.category.name];
[fetchRequest setPredicate:requestPredicate];
//将批量大小设置为合适的数量。
[fetchRequest setFetchBatchSize:20];
//根据需要编辑排序键。
NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@nameascending:YES];
NSArray * sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor,nil];
[fetchRequest setSortDescriptors:sortDescriptors];
//如果适当,编辑段名称键路径和缓存名称。
//节的名称键路径的nil表示没有节。

NSFetchedResultsController * aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;


[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];

NSError * error = nil;
if(![self.fetchedResultsController performFetch:& error])
{
// TO DO:错误的东西
NSLog(@Unresolved error%@,%@ ,error,[error userInfo]);
abort();
}

return fetchedResultsController;
}


#pragma mark - 获取的结果控制器委托


- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id< NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType: (NSFetchedResultsChangeType)type
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;

case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView * tableView = self.tableView;

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];
break;

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


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}

@end


解决方案>

您的设计错了。您不应该在任何位置添加行,但在逻辑上它们在表中。



获取结果控制器(FRC)的整个点是将tableview与数据同步。表中的行的顺序应反映fetchedObjects数组中托管对象的顺序。通过在底部或顶部插入一行,同时添加不一定在逻辑上属于表的顶部或底部的对象,则会中断同步。



当在 addingViewController:didAdd:中添加一个新的托管对象时,FRC会提示它委托,它尝试重绘表。你试图补偿这一点,但你真的不能。所有的索引都会消失。



而不是使用一行来输入新行。使用tableview标题或页脚视图。这样,你可以冻结tableview,创建新的对象,然后更新表,新的对象将显示在逻辑属于表中的哪里。


When the user presses Edit, my UITableView adds an insert row at the top (with a green plus), and puts all the other rows into delete mode (red minus). Alternatively, the user can swipe-to-delete without pressing the edit button. I am using a couple of Ivars to keep track of whether the table is in edit mode from a swipe, or from pressing the edit button, and act accordingly (e.g. updating numberOfRowsInTableView: with the extra insert row when Edit has been pressed).

Everything works perfectly except on thing: when in Edit mode (i.e. the user has explicitly hit the edit button, and the insert row has appeared at the top), if the user tries to delete the bottom row, the next row up gets deleted instead. Deleting any other row is fine.

EDIT -- It appears to delete the row above, but if I immediately quit and reload the app, it turns out the bottom row has gone after all. So I'm guessing my UITableView is going out of sync with my NSFetchedResultsController somewhere.

Here's the code I'm using:

#import "ChecklistsViewController.h"
#import "Checklist.h"

@interface ChecklistsViewController (private)
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
- (void)addingView;
@end


@implementation ChecklistsViewController

@synthesize category, managedObjectContext, fetchedResultsController;


- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        editingFromSwipe = NO;
        tableIsEditing = NO;
    }
    return self;
}

- (void)dealloc
{
    [category release];
    [managedObjectContext release];
    [fetchedResultsController release];
    [super dealloc];
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    editingFromSwipe = NO;
    tableIsEditing = NO;
    self.navigationItem.rightBarButtonItem = self.editButtonItem;    
    self.tableView.allowsSelectionDuringEditing = YES;
}


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    int rows = [sectionInfo numberOfObjects];

    if (self.editing) {
        if (!editingFromSwipe && tableIsEditing) {
            return rows +1;
        }
        return rows;
    }
    tableIsEditing = NO;
    return rows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

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

    // Configure the cell...
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;


    NSLog(@"Should go into if statement here! \n");

    if (tableView.editing) { //
        if ((indexPath.row == 0) && (!editingFromSwipe)) {
            NSLog(@"Configuring Add Button Cell while editing \n");
            cell.textLabel.text = @"Add New Checklist";
            cell.detailTextLabel.text = nil;
        }
        else {
            NSLog(@"Configuring other cells while editing \n");
            [self configureCell:cell atIndexPath:indexPath];
        }

    }
    else {
        NSLog(@"Configuring Cell Normally While Not Editing \n");
        [self configureCell:cell atIndexPath:indexPath];
    }


    return cell;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        // Delete the managed object for the given index path
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];

        int numberOfRows = [self tableView:tableView numberOfRowsInSection:indexPath.section];
        int rowBeingDeleted = indexPath.row +1;

        if (tableIsEditing && !editingFromSwipe && numberOfRows == rowBeingDeleted) {
            [context deleteObject:[self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section]]];
        }
        else {
            [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
        }

        // Save the context.
        NSError *error = nil;
        if (![context save:&error])
        {
            // TO DO: Fix error code.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }    
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        [self addingView];        
    }   
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    int row = indexPath.row;

    if (self.editing && row == 0) {
        if (!editingFromSwipe && tableIsEditing) {
            return UITableViewCellEditingStyleInsert;
        }
        else if (editingFromSwipe) { 
            return UITableViewCellEditingStyleDelete;
        }

    }
    return UITableViewCellEditingStyleDelete;
}


- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    editingFromSwipe = YES;
    [super tableView:tableView willBeginEditingRowAtIndexPath:indexPath];
}

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    [super tableView:tableView didEndEditingRowAtIndexPath:indexPath];
    editingFromSwipe = NO;
}


- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];

    NSArray *addRow = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:0 inSection:0], nil];
    [self.tableView beginUpdates];

    if (!editingFromSwipe) {
        if (editing) {
            tableIsEditing = YES;
            [self.tableView insertRowsAtIndexPaths:addRow withRowAnimation:UITableViewRowAnimationLeft];
        }
        else {
           [self.tableView deleteRowsAtIndexPaths:addRow withRowAnimation:UITableViewRowAnimationLeft];
        } 
    }
    [self.tableView endUpdates];
}


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row != 0) {
        TO DO: Code for when row is selected
    }
}


#pragma mark - Data


- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    Checklist *aChecklist = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = aChecklist.name;
    cell.detailTextLabel.text = aChecklist.category.name;
}


- (void) addingView// :(id)sender
{
    AddingViewController *viewController = [[AddingViewController alloc] initWithNibName:@"AddingViewController" bundle:nil];

    viewController.delegate = self;
    viewController.title = @"Add Checklist";

    // Create the navigation controller and present it modally
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
    [self presentModalViewController:navigationController animated:YES];

    viewController.textLabel.text = @"Enter new checklist name";

    [navigationController release];
    [viewController release];
}


#pragma mark - AddingViewDelegate


- (void)addingViewController:(AddingViewController *)addingViewController didAdd:(NSString *)itemAdded
{
    if (itemAdded != nil) {

        // Turn off editing mode.
        if (self.editing) [self.navigationController setEditing:NO animated:NO];

        // Add the category name to our model and table view.

        // Create a new instance of the entity managed by the fetched results controller.
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
        NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
        Checklist *newChecklist = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

        [category addChecklistsObject:newChecklist];

        newChecklist.name = itemAdded;        
        // [newChecklist setDateStamp:[NSDate date]];

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


    }

    [self dismissModalViewControllerAnimated:YES];
}


#pragma mark - Fetched results controller

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

    // Set up the fetched results controller.

    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Checklist" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    // Set 4* the predicate so we only see checklists for this category.
    NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"category.name = %@", self.category.name];
    [fetchRequest setPredicate:requestPredicate];    
    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];    
    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];    
    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".    

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                                                                                managedObjectContext:self.managedObjectContext 
                                                                                                  sectionNameKeyPath:nil 
                                                                                                           cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;


    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error])
    {
       // TO DO: error stuff
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return fetchedResultsController;
} 


#pragma mark - Fetched results controller delegate


- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    switch(type)
    {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;

    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];
            break;

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


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
}

@end

解决方案

Your design it at fault. You shouldn't be adding rows anywhere but where they logically go in the table.

The entire point of a fetched results controller (FRC) is to synchronize the tableview with the data. The order of the rows in the table should reflect the order of managed objects in the fetchedObjects array. By inserting a row at the bottom or top and while adding an object that does not necessarily logically belong at the top or bottom of the table, are breaking that synchronization.

When you add a new managed object in addingViewController:didAdd: the FRC alerts it delegate which tries to redraw the table. You've tried to compensate for this but you really can't. All you indexes are coming off.

Instead of using a row to input new rows. Use a tableview header or footer view. That way, you can freeze the tableview, create the new object, then update the table and the new object will show up where it logical belongs in the table.

这篇关于为什么我不能删除我的UITableView的底行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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