Come limitare il riordino delle righe di UITableView a una sezione

Mi stavo battendo la testa su questo, e google stava rivelando nulla. Alla fine ho lavorato e ho pensato di scriverlo qui per il bene della prossima persona.

Hai un UITableView con più sezioni. Ogni sezione è omogenea, ma la tabella generale è eterogenea. Pertanto, potresti voler consentire il riordino delle righe all’interno di una sezione, ma non tra le sezioni. Forse vuoi anche solo volere che una sezione sia riordinabile (era il mio caso). Se stai cercando, come ero io, su UITableViewDataSourceDelegate , non troverai una notifica per quando è in procinto di permetterti di spostare una riga tra le sezioni. Ne prendi uno quando inizia a spostare una riga (che va bene) e uno quando è già stato spostato e hai la possibilità di sincronizzarti con le tue cose interne. Non d’aiuto.

Quindi, come puoi evitare riordini tra le sezioni?

Pubblicherò ciò che ho fatto come una risposta separata, lasciandolo aperto a qualcun altro per pubblicare una risposta ancora migliore!

Questa implementazione impedirà il riordino al di fuori della sezione originale come la risposta di Phil, ma scatterà anche il record sulla prima o sull’ultima riga della sezione, a seconda di dove è andato il trascinamento, invece di dove è iniziato.

 - (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; } 

Abbastanza semplice, davvero.

UITableViewDelegate ha il metodo:

 tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: 

Questo viene chiamato mentre l’utente sta passando sopra un potenziale punto di rilascio. Hai la possibilità di dire “no, non lasciarlo lì! Butta qui invece”. È ansible restituire un percorso dell’indice diverso da quello proposto.

Tutto quello che ho fatto è stato controllare se gli indici delle sezioni corrispondono. Se lo fanno poi bene, restituisci il percorso proposto. in caso contrario, restituire il percorso di origine. Ciò impedisce anche alle file di altre sezioni di spostarsi mentre si trascina, e la riga trascinata tornerà alla posizione originale in cui si tenta di spostarla in un’altra sezione.

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

Swifty versione veloce della risposta di Jason per voi pigri:

 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 } 

Puoi impedire lo spostamento delle file tra le sezioni usando il metodo seguente. Basta non consentire alcun movimento tra le sezioni. Puoi persino controllare il movimento di una riga specifica all’interno di una sezione. ad es. ultima riga in una sezione.

Ecco l’esempio:

 - (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; } } 

Di @ Jason Harwig, il codice qui sotto funziona correttamente.

 - (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 } 

Per non modificare la posizione tra le sezioni Swift3

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