Как ограничить переупорядочение строки UITableView в разделе

Я ударился головой об этом, и google ничего не показывал. В конце концов я решил это сделать и подумал, что я напишу его здесь для следующего человека.

У вас есть UITableView с несколькими разделами. Каждый раздел является однородным, но таблица в целом неоднородна. Таким образом, вы можете разрешить переупорядочивание строк внутри раздела, но не через разделы. Может быть, вы даже хотите, чтобы одна часть была переупорядочиваемой вообще (это было моим делом). Если вы ищете, как я был, в UITableViewDataSourceDelegate, вы не найдете уведомления о том, когда он собирается переместить строку между разделами. Вы получаете тот, когда он начинает перемещать строку (и это хорошо), и один, когда он уже перемещает ее, и вы получаете возможность синхронизироваться со своими внутренними вещами. Не полезно.

Итак, как вы можете предотвратить повторные заказы между разделами?

Я опубликую то, что я сделал как отдельный ответ, оставив его открытым, чтобы кто-то еще опубликовал еще лучший ответ!

Ответ 1

Эта реализация предотвратит переупорядочивание вне исходного раздела, например, ответа Фила, но также привяжет запись к первой или последней строке раздела, в зависимости от того, где было перемещено, а не там, где оно было начато.

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

Ответ 2

Достаточно просто.

UITableViewDelegate имеет способ:


tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

Это вызвано, пока пользователь зависает над потенциальной точкой падения. У вас есть шанс сказать: "Нет, не бросайте его туда! Бросьте сюда сюда". Вы можете вернуть другой путь указателя к предлагаемому.

Все, что я сделал, это проверить, соответствуют ли индексы раздела. Если они это сделают, тогда верните предложенный путь. если нет, верните исходный путь. Это также прекрасно предотвращает перемещение строк в других разделах, когда вы перетаскиваете их, а перетаскиваемая строка будет привязана к исходной позиции, которую вы пытаетесь переместить в другую секцию.


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

Ответ 3

Быстрая версия Джейсона отвечает за ленивых людей:

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
}

Ответ 4

Вы можете предотвратить перемещение строк между разделами, используя метод ниже. Просто не допускайте движения между секциями. Вы можете даже контролировать движение определенной строки внутри раздела. например, последняя строка в разделе.

Вот пример:

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

Ответ 5

Чем @Джейсон Харвиг, код ниже работает правильно.

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

Ответ 6

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
}

Ответ 7

Для изменения положения между разделами Swift3

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