在我的应用中,会向用户显示一个数据表。当他们点击“编辑”时,顶部会显示一个带有绿色加号的编辑行 - 他们可以使用此行将另一个项目添加到列表中。
当用户点击编辑按钮时,此功能正常,但如果用户使用滑动删除,则会显示编辑行(没有绿色加号),一切都变得奇怪(删除按钮出现在错误的行上,等等)。
谁能告诉我我做错了什么?对不起,只是为了转储大量的代码,但我已经在这么多圈子里走了一圈,我已经失去了所有的观点!
#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) {
editControlsDidShow = NO;
}
return self;
}
- (void)dealloc
{
[category release];
[managedObjectContext release];
[fetchedResultsController release];
[super dealloc];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.tableView.allowsSelectionDuringEditing = YES;
}
#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];
if (tableView.editing) return [sectionInfo numberOfObjects] +1;
return [sectionInfo numberOfObjects];
}
- (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;
[self configureCell:cell atIndexPath:indexPath];
if (tableView.editing) {
if (indexPath.row == 0) {
cell.textLabel.text = @"Add New Checklist";
cell.detailTextLabel.text = nil;
}
if (indexPath.row != 0) {
[self configureCell:cell atIndexPath:indexPath];
}
}
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![context save:&error])
{
// 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 (editControlsDidShow) return UITableViewCellEditingStyleInsert;
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleDelete;
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
editControlsDidShow = NO;
[super setEditing:editing animated:animated];
NSArray *addRow = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:0 inSection:0], nil];
[self.tableView beginUpdates];
if (editing) {
editControlsDidShow = 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
{
// not done yet
}
#pragma mark - Data
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
Checklist *aChecklist = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [aChecklist.name description];
cell.detailTextLabel.text = [aChecklist.category.name description];
}
- (void) addingView// :(id)sender
{
//Create the root view controller for the navigation controller
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];
// 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;
NSError *error = nil;
if (![context save:&error])
{
// error code
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
// 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.
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])
{
// handle the error properly!
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
答案 0 :(得分:2)
我发现了一件你可能想要改变的事情:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
我认为您不希望编辑行可编辑。这是修复它的代码:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return (indexPath.row != 0);
}
你可能想要一个if else来让它更具可读性,但如果你很懒,这就足够了。
你还可以指出你添加绿色加号的位置吗?你做的时候我会更新我的答案。
编辑:问题是当您使用滑动删除时,只有您滑动的行会进入编辑模式。编辑行不进入编辑模式,因此不显示绿色加号。如果删除按钮出现在错误的行上,我会认为问题是当表视图进入编辑模式时,会添加编辑行,这会更新所有连续行的indexPath。
截至目前,我无法提供任何解决问题的代码,但我可以为您提供一个想法。当用户使用滑动到删除时,您不应添加编辑行。如果您可以识别何时使用滑动到删除,并且不根据您的问题应该解决添加编辑行。我从来没有遇到类似的问题,所以我从来没有这样做过。因此,我无法提供有关如何执行此操作的详细信息。
如果您需要更多/更好的建议或帮助实施,请告诉我。
答案 1 :(得分:2)
我遇到了同样的问题,我只是用这个技巧解决了这个问题:
您可以检查 编辑模式如何设置为YES:
- (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;
}
我猜你已经知道如何从这一点开始,只有当editingFromSwipe为零时才创建一个if-function插入add-row-row。
我认为我们都同意Apple在这里不太合作。我希望它有所帮助!