Управление переупорядочением строк

Табличное представление имеет режим редактирования, а также его нормальное (выбор) режим. Когда табличное представление входит в режим редактирования, оно выводит на экран редактирование и переупорядочение средств управления, связанных с его строками. Управление переупорядочением позволяет пользователю перемещать строку в различное расположение в таблице. Как показано на рисунке 8-1, управление переупорядочением появляется на правой стороне строки.

Рисунок 8-1  , Переупорядочивающий строку
Reordering a row

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

Когда строка Перемещена, что Происходит

Табличное представление входит в режим редактирования, когда это получает a setEditing:animated: сообщение. Это обычно происходит, когда пользователь касается кнопки Edit в панели навигации, но можно реализовать собственные средства управления, если Вы желаете. В режиме редактирования табличное представление выводит на экран любое переупорядочение и редактирование средств управления, которые его делегат присвоил каждой строке. Делегат присваивает средства управления в tableView:cellForRowAtIndexPath: путем установки showsReorderControl свойство UITableViewCell объекты к YES. Для средств управления переупорядочиванием для появления источник данных должен поддерживать переупорядочение путем реализации tableView:moveRowAtIndexPath:toIndexPath: метод.

Когда табличное представление получает setEditing:animated:, это отправляет то же сообщение в UITableViewCell объект для каждой видимой строки. Тогда это отправляет преемственность сообщений к ее источнику данных и ее делегату (если они реализуют методы), как изображено в схеме на рисунке 8-2.

  Вызывающая последовательность рисунка 8-2 для переупорядочения строки в табличном представлении
Calling sequence for reordering a row in a table view

Когда табличное представление получает setEditing:animated: сообщение, это снова посылает то же сообщение объектам ячейки, соответствующим ее видимым строкам. После этого последовательность сообщений следующие:

  1. Табличное представление отправляет a tableView:canMoveRowAtIndexPath: обменивайтесь сообщениями к его источнику данных (если это реализует метод). В этом методе делегат может выборочно исключить определенные строки из показа управления переупорядочением.

  2. Пользователь перетаскивает строку ее управлением переупорядочением или вниз табличным представлением. Поскольку перетащенная строка нависает над частью табличного представления, базовая строка скользит вниз для показа, где место назначения было бы.

  3. Каждый раз, когда перетащенная строка по месту назначения, табличное представление отправляет tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: его делегату (если это реализует метод). В этом методе делегат может отклонить текущее место назначения для перетащенной строки и указать альтернативную.

  4. Табличное представление отправляет tableView:moveRowAtIndexPath:toIndexPath: к его источнику данных (если это реализует метод). В этом методе источник данных обновляет массив модели данных, который является источником элементов для табличного представления, перемещая элемент в различное расположение в массиве.

Примеры перемещения строки

Этот раздел комментирует некоторый пример кода, иллюстрирующий шаги переупорядочения, перечисленные в том, Что Происходит, Когда Перемещена строка. Перечисление 8-1 показывает реализацию tableView:canMoveRowAtIndexPath: это исключает первую строку в табличном представлении от того, чтобы быть переупорядоченным (эта строка не имеет контроля переупорядочением).

Перечисление 8-1  , Исключая строку от перемещения

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 0) // Don't move the first row
      return NO;
 
   return YES;
}

Когда пользователь заканчивает перетаскивать строку, она скользит в ее место назначения в отправляющем табличном представлении, tableView:moveRowAtIndexPath:toIndexPath: к его источнику данных. Перечисление 8-2 показывает реализацию этого метода.

Перечисление 8-2  , Обновляющее модель данных, выстраивает для перемещенной строки

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
    NSString *stringToMove = [self.reorderingRows objectAtIndex:sourceIndexPath.row];
    [self.reorderingRows removeObjectAtIndex:sourceIndexPath.row];
    [self.reorderingRows insertObject:stringToMove atIndex:destinationIndexPath.row];
}

Делегат может также перенастроить предложенное место назначения для перемещения к другой строке путем реализации tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: метод. Следующий пример ограничивает строки перемещением в их собственной группе и предотвращает перемещения к последней строке группы (который резервируется для заполнителя добавлять-элемента).

Перечисление 8-3  , Перенастраивающее целевую строку операции пересылки

- (NSIndexPath *)tableView:(UITableView *)tableView
        targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
        toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
    NSDictionary *section = [data objectAtIndex:sourceIndexPath.section];
    NSUInteger sectionCount = [[section valueForKey:@"content"] count];
    if (sourceIndexPath.section != proposedDestinationIndexPath.section) {
        NSUInteger rowInSourceSection =
             (sourceIndexPath.section > proposedDestinationIndexPath.section) ?
               0 : sectionCount - 1;
        return [NSIndexPath indexPathForRow:rowInSourceSection inSection:sourceIndexPath.section];
    } else if (proposedDestinationIndexPath.row >= sectionCount) {
        return [NSIndexPath indexPathForRow:sectionCount - 1 inSection:sourceIndexPath.section];
    }
    // Allow the proposed destination.
    return proposedDestinationIndexPath;
}