如何限制UITableView行重新sorting到一个部分

我正在为这个问题而头痛,谷歌什么也没有。 我最终解决了这个问题,并认为我会为了下一个人而写在这里。

你有一个UITableView与多个部分。 每个部分是同质的,但表格总体上是不均匀的。 因此,您可能希望允许在某个部分中对行进行重新sorting,但不能部分进行sorting。 也许你只想要一个部分可以根据需要重新订购(这是我的情况)。 如果你正在寻找,就像在UITableViewDataSourceDelegate你不会find一个通知,告诉你什么时候可以让你在一个段之间移动一行。 当它开始移动一行时(这是很好的),当它已经移动它时,你会得到一个,你有机会与你的内部的东西同步。 没有帮助。

那么如何防止部分之间的重新订购呢?

我将发布我做的一个单独的答案,让其他人发布更好的答案!

这个实现将防止像Phil的答案那样在原始部分之外重新sorting,但是它也会将logging捕捉到该部分的第一行或最后一行,具体取决于拖动的位置,而不是它开始的位置。

 - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { if (sourceIndexPath.section != proposedDestinationIndexPath.section) { NSInteger row = 0; if (sourceIndexPath.section < proposedDestinationIndexPath.section) { row = [tableView numberOfRowsInSection:sourceIndexPath.section] - 1; } return [NSIndexPath indexPathForRow:row inSection:sourceIndexPath.section]; } return proposedDestinationIndexPath; } 

很简单,真的。

UITableViewDelegate的方法是:

 tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: 

当用户hover在可能的下降点上时,这被调用。 你有机会说,“不!不要把它放在那里,而是把它放在这里”。 你可以返回一个不同的索引path到build议的path。

我所做的只是检查部分索引是否匹配。 如果他们做得很好,则返回提出的path。 如果没有,则返回源path。 这也很好地防止了其他部分中的行随着拖动而移动 – 拖动的行将回到原来的位置,尝试将其移动到另一部分。

 - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { if( sourceIndexPath.section != proposedDestinationIndexPath.section ) { return sourceIndexPath; } else { return proposedDestinationIndexPath; } } 

杰森的答案swifty迅捷版为你懒人:

 override func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath { if sourceIndexPath.section != proposedDestinationIndexPath.section { var row = 0 if sourceIndexPath.section < proposedDestinationIndexPath.section { row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1 } return NSIndexPath(forRow: row, inSection: sourceIndexPath.section) } return proposedDestinationIndexPath } 

使用下面的方法可以防止段之间的行移动。 只是不允许部分之间的任何移动。 您甚至可以控制某个部分内特定行的移动。 例如一节中的最后一行。

这是一个例子:

 - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { // Do not allow any movement between section if ( sourceIndexPath.section != proposedDestinationIndexPath.section) { return sourceIndexPath; } // You can even control the movement of specific row within a section. eg last row in a Section // Check if we have selected the last row in section if (sourceIndexPath.row < sourceIndexPath.length) { return proposedDestinationIndexPath; } else { return sourceIndexPath; } } 

比@Jason Harwig,下面的代码工作正常。

 - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { if (sourceIndexPath.section != proposedDestinationIndexPath.section) { NSInteger row = 0; if (sourceIndexPath.section < proposedDestinationIndexPath.section) { row = [tableView numberOfRowsInSection:sourceIndexPath.section] - 1; } return [NSIndexPath indexPathForRow:row inSection:sourceIndexPath.section]; } return proposedDestinationIndexPath; } 

Swift 3:

 override func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath { if sourceIndexPath.section != proposedDestinationIndexPath.section { var row = 0 if sourceIndexPath.section < proposedDestinationIndexPath.section { row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1 } return IndexPath(row: row, section: sourceIndexPath.section) } return proposedDestinationIndexPath } 

为了不改变部分Swift3之间的位置

 override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath { if originalIndexPath.section != proposedIndexPath.section { return originalIndexPath } else { return proposedIndexPath } }