Je frappais ma tête sur celui-ci, et Google ne montait rien. Je l'ai finalement résolu et j'ai pensé l'écrire ici pour le bien de la prochaine personne.
Vous avez un UITableView
avec plusieurs sections. Chaque section est homogène, mais le tableau dans son ensemble est hétérogène. Donc, vous voudrez peut-être autoriser le réordonnancement des lignes dans une section, mais pas les sections across. Peut-être que vous ne voulez même qu'une section soit réorganisable (c'était mon cas). Si vous regardez, comme je l'étais, dans le UITableViewDataSourceDelegate
, vous ne trouverez pas de notification quand il est sur le point de vous permettre de déplacer une ligne entre les sections. Vous en obtenez un lorsqu'il commence à déplacer une ligne (ce qui est bien) et un lorsqu'il est déjà déplacé et vous avez la possibilité de vous synchroniser avec vos données internes. Inutile.
Alors, comment pouvez-vous empêcher les nouvelles commandes entre les sections?
Je posterai ce que j'ai fait comme réponse séparée, en laissant ouverte à quelqu'un d'autre de poster une réponse encore meilleure!
Cette implémentation empêchera de réorganiser en dehors de la section d'origine comme la réponse de Phil, mais elle alignera également l'enregistrement sur la première ou la dernière ligne de la section, en fonction de l'endroit où le glissement est allé, plutôt que de l'endroit où il a commencé.
- (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;
}
Assez simple, vraiment.
UITableViewDelegate a la méthode:
tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
Cela est appelé pendant que l'utilisateur survole un point de chute potentiel. Vous avez la possibilité de dire: "non! Ne le laissez pas tomber ici! Déposez-le ici à la place". Vous pouvez renvoyer un chemin d'index différent de celui proposé.
Je n'ai fait que vérifier si les indices de section correspondent. S'ils s'en sortent bien, renvoyez le chemin proposé. sinon, renvoyez le chemin source. Cela empêche également les lignes des autres sections de bouger lorsque vous faites glisser - et la ligne glissée reviendra à sa position d'origine si vous essayez de la déplacer vers une autre section.
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
if( sourceIndexPath.section != proposedDestinationIndexPath.section )
{
return sourceIndexPath;
}
else
{
return proposedDestinationIndexPath;
}
}
Swifty Swift version de la réponse de Jason pour vous les paresseux:
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
}
Vous pouvez empêcher le mouvement des lignes entre les sections en utilisant la méthode ci-dessous. Ne laissez tout simplement aucun mouvement entre les sections. Vous pouvez même contrôler le mouvement d'une ligne spécifique dans une section. par exemple la dernière ligne d'une section.
Voici l'exemple:
- (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. e.g 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;
}
}
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
}
Que @Jason Harwig, le code ci-dessous fonctionne correctement.
- (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;
}
Pour ne pas changer de position entre les sections Swift
override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
if originalIndexPath.section != proposedIndexPath.section
{
return originalIndexPath
}
else
{
return proposedIndexPath
}
}