在UITableView中点击已选择的单元格时,将调用willSelectCellAtIndexPath

时间:2013-03-13 20:14:20

标签: ios objective-c uitableview

我有一个UITableView,有两个部分。根据用户交互(选择和取消选择),我的数据源和UITableView会更新,以便在各个部分之间移动数据。最初它们只是第0部分中的数据。当我点击一个单元格时,willSelectCellAtIndexPathdidSelectCellAtIndexPath被调用。正如预期的那样,当我再次点击同一个单元格时,会调用didDeselectCellAtIndexPath

即使我开始将数据移至第1部分并选择并取消选择,也会适当调用UITableView's委托方法。

将所有数据移至第1部分后,UITableView开始出现奇怪的行为。我最初可以选择一个电话,并调用didSelectCellAtIndexPath。但是,当我再次点击它时,永远不会调用didDeselectCellAtIndexPath。相反,所选单元格上的任何点击(我已确认通过[tableView indexPathsForSelectedCells]或第1节中的任何其他单元确实选中它只会导致调用willSelectIndexPathdidSelectIndexPath

我在这些委托方法中有相当多的代码是无关的(我相信)....我没有明确地改变单元格的选定状态。我发布了willSelect方法,如有必要,可以发布更多内容。

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (remainingItemIsSelected && indexPath.section == 0) {
        //other cells in the remaining items section are selected and a cell from that section is being selected

        NSMutableIndexSet *arrayIndexesToBeDeleted = [[NSMutableIndexSet alloc] init];
        for (NSIndexPath *previouslySelectedIndexPath in [tableView indexPathsForSelectedRows]) {
            if (((ReceiptItem *)[self.remainingReceiptItems objectAtIndex:previouslySelectedIndexPath.row]).allocated == YES) {

                //update data sources
                NSLog(@"%@%i%@,%i",@"Section #:",previouslySelectedIndexPath.section,@" Row #:",previouslySelectedIndexPath.row);
                [self.assignedReceiptItems addObject:[self.remainingReceiptItems objectAtIndex:previouslySelectedIndexPath.row]];
                [arrayIndexesToBeDeleted addIndex:previouslySelectedIndexPath.row];

                //update index path arrays
                [self.receiptItemsToDeleteIndexPaths addObject:previouslySelectedIndexPath];
                [self.receiptItemsToAddIndexPaths addObject:[NSIndexPath indexPathForRow:self.assignedReceiptItems.count-1 inSection:1]];

                //update the pressed indexpath to equal to resulting indexpath to pass on to the didSelect method
                if (previouslySelectedIndexPath.row < indexPath.row) {
                    indexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:0];
                }
            }
        }
        //Delete assigned items from the remaining receipt items
        [self.remainingReceiptItems removeObjectsAtIndexes:arrayIndexesToBeDeleted];
        //update table (move allocated item down)
        [tableView beginUpdates];
        [tableView deleteRowsAtIndexPaths:self.receiptItemsToDeleteIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
        [tableView insertRowsAtIndexPaths:self.receiptItemsToAddIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
        [tableView endUpdates];
        if (self.remainingReceiptItems.count == 0) {
            [tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
        }
        //other cells in the remaining items section are selected and a cell from assigned items is being selected
        return nil;
    }
    return indexPath;
}

1 个答案:

答案 0 :(得分:1)

来自Documentation for UITableViewDelegate

  

<强>的tableView:willDeselectRowAtIndexPath:
  仅当用户尝试选择其他行时存在现有选择时,才会调用此方法。代理将为先前选定的行发送此方法。

如果你认为这一点,你会发现你遇到的是预期的行为。点击选中的行在此行上调用will/didDeselctRowAtIndexPath

相反,您可以在didSelectRowAtIndexPath中为所选行处理此问题,即在那里取消选择。

可能的替代方案

话虽如此,我认为你正在滥用UITableView课程。它真的不是为了做这个移动的东西。毫无疑问,你必须注意自己必须编写大量代码才能使其工作 - 这就是你遇到棘手错误的原因。

在我看来,一个更清晰(并且最终更灵活)的解决方案是拥有两个独立的表(或其他)视图,这些视图通过代理通过datasource更改通知对方。也许更多的工作可以设置它,但肯定会减少麻烦。