3

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

即使在我开始将数据向下移动到第 1 部分并选择和取消选择之后,UITableView's委托方法也会被适当地调用。

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

我在这些委托方法中有相当多的代码是不相关的(我相信)......我没有在任何地方显式地更改单元格的选定状态。我已经发布了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;
}
4

1 回答 1

1

UITableViewDelegate 的文档中

tableView:willDeselectRowAtIndexPath:
仅当用户尝试选择不同的行时存在现有选择时才调用此方法。为先前选择的行向委托发送此方法。

如果你这样想,你会发现你遇到的是预期的行为。点击选中的行不会调用will/didDeselctRowAtIndexPath该行。

相反,您可以didSelectRowAtIndexPath为选定的行处理这个,即在那里取消选择它。

可能的替代方案

话虽如此,我认为你在滥用UITableView班级。它真的不是为了做这些动人的事情而设计的。毫无疑问,您已经注意到自己必须编写大量代码才能完成这项工作——这正是您遇到棘手错误的原因。

It seems to me that a much cleaner (and ultimately more flexible) solution would be to have two separate table (or other) views that notify each other via delegates about datasource changes. Maybe a bit more work setting it up, but surely much less trouble down the road.

于 2013-03-13T23:05:44.643 回答