Главная iPhone Mac OS X Форум О себе

Режим редактирования таблиц

Табличные данные, представленные в элементах UITableView, нередко требуют интерактивного взаимодействия с пользователем: удаления и добавления строк во время работы программы. Для этих целей у UITableView и вспомогательных классов заготовлено несколько простых и удобных методов, которым я посвящу сегодняшний пост.

Под наши эксперименты мы возьмем один из старых проектов, который я использовал для демонстрации работы с UITableView, добавив в его интерфейс UINavigationController. Чтобы не мучать вас описанием этого процесса, предлагаю скачать его исходники и ознакомиться с ними самостоятельно.

Табличное приложение для iPhone

Скачать архив (15Кб)

Интерактивное удаление строк из таблицы

У нас имеется список компаний и мы бы хотели дать возможность пользователю удалить некоторые из них. Весь процесс перевода таблицы в режим редактирования состоит в использовании предопределенных и реализации некоторых виртуальных методов.

UIViewController имеет в своем арсенале предопределенный метод editButtonItem, который возвращает объект класса UIBarButtonItem, описывающий кнопку редактирования и закрепленные за ней действия, ответственные за реализацию нажатия, переключение состояний кнопки и отправку сообщений в редактируемый объект. Воспользуемся элементом Navigation Bar для размещения кнопки в интерфейсе приложения. Ее инициализацию опишем в методе awakeFromNib класса tableViewController.


self.navigationItem.leftBarButtonItem = self.editButtonItem;

Кнопка редактирования в интерфейсе таблицы

Каждый раз при нажатии на кнопку “Edit” в объект UIViewController отправляется сообщение setEditing:YES animated:YES. Как обычно, его реализация остается на наших плечах и состоит всего из двух строк.


— (void)setEditing:(BOOL)editing animated:(BOOL)animate {
    [super setEditing:editing animated:animate];
    [listView setEditing:editing animated:animate];
}

Первой мы обеспечиваем установку внутреннего индикатора режима редактирования — переменной editing у UIViewController, а во второй переводим таблицу в режим редактирования, что приводит к появлению “красных минусов” — кнопок удаления в каждой ячейке таблицы. Окончание редактирования, инициированное повторным нажатием на кнопку, вызывает отправку все того же сообщения setEditing:animated:, но с первым параметром установленным в значение NO.

Процесс удаления ячейки проходит в два этапа: на первом вы нажимаете кнопку с минусом в выбранной строке, а на втором подтверждаете удаление нажатием на кнопку Delete.

Процесс удаления ячейки из таблицы

Сам процесс удаления описывает метод tableView:commitEditingStyle:forRowAtIndexPath: протокола UITableViewDataSource.


— (void)tableView:(UITableView *)tableView
                        commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
                         forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [list removeObjectAtIndex:indexPath.row];
        [listView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                              withRowAnimation:UITableViewRowAnimationFade];
    }
}

Параметр editingStyle может принимать значение UITableViewCellEditingStyleInsert или UITableViewCellEditingStyleDelete в зависимости от действия, применяемого к ячейке. В нашем случае мы обрабатываем только операции удаления. Следующей строкой мы удаляем из массива элемент в указанной в indexPath позиции, а затем визуализуем процесс удаления вызовом метода deleteRowsAtIndexPaths:withRowAnimation:. Первый параметр содержим массив объектов NSIndexPath, несущих координаты удаляемых строк. То есть в общем виде мы можем удалить далеко не одну строчку, вдобавок красиво анимировав весь процесс, за что отвечает следующий параметр. UITableViewRowAnimation указывает тип анимации при удалении строки: это может быть сдвиг строки вправо, влево, вверх, вниз или растворение.

Реализация двух методов и добавление одной строчки в код — это все, что от вас требуется для создания редактируемой таблицы.

Скачать архив (15Кб)

Но может вы хотите большего? Хотите знать…

…как все устроено?

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

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

Во-первых, кнопку мы бы создали самостоятельно.


UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:@"Edit"
                                                               style:UIBarButtonItemStyleBordered
                                                              target:self
                                                              action:@selector(editAction:)];
self.navigationItem.leftBarButtonItem = editButton;
[editButton release];

Во-вторых, в реализации метода editAction нам потребуется написать:

  • отправку сообщений setEditing:animated: в UIViewController
  • переключение кнопки между состоянием Edit/Done в зависимости от текущего режима редактирования

За индикацию режима редактирования отвечает переменная editing объекта UIViewController. Благодаря ей реализация первого пункта будет выглядеть следующим образом.


-(void)editAction:(id)sender {
    if (self.editing) {
        [self setEditing:NO animated:YES];
    } else {
        [self setEditing:YES animated:YES];
    }
}

Чтобы изменить состояние кнопки нам потребуется всего лишь изменить подпись к ней.


-(void)editAction:(id)sender {
    if (self.editing) {
        [self setEditing:NO animated:YES];
        self.navigationItem.leftBarButtonItem.title = @"Edit";
    } else {
        [self setEditing:YES animated:YES];
        self.navigationItem.leftBarButtonItem.title = @"Done";
    }
}

Реализация метода setEditing:animated: остается без изменений.


— (void)setEditing:(BOOL)editing animated:(BOOL)animate {
    [super setEditing:editing animated:animate];
    [listView setEditing:editing animated:animate];
}

Мы увидели как работает элемент изнутри и теперь в случае необходимости сможем применить полученные знания, например, для произвольной инициализации кнопки редактирования таблицы. Хотите пойти еще дальше, узнать еще больше? Ведь я еще ни слова не сказал об интерактивной вставке строк в таблицу.

Скачать архив (15Кб)

Интерактивное добавление строк в таблицу

Каждая ячейка может быть представлена в трех состояниях при нахождении в режиме редактирования: отсутствие действий, разрешать удаление или разрешать вставку новой ячейки. По умолчанию все ячейки отмечаются как готовые к удалению, но их стиль можно поменять в реализации метода tableView:editingStyleForRowAtIndexPath:.


— (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
           editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewCellEditingStyleInsert;
}

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

Кнопки добавления строк в таблицу

За обработку нажатий отвечает, как и в предыдущем примере, tableView:commitEditingStyle:forRowAtIndexPath:


— (void)tableView:(UITableView *)tableView
                        commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
                         forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleInsert) {
        [list insertObject:@"INSERTED!" atIndex:indexPath.row];
        [listView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }
}

В нашем примере при нажатии на “плюс” добавляется строчка с надписью “INSERTED!” перед выбранной ячейкой. Процесс добавления кардинально ничем не отличается от процедуры удаления и так же прост, как и все, с чем мы сегодня успели ознакомиться.

Добавленная строчка в таблицу

Напоследок хочу рассказать о способе фильтрации ячеек, который можно применять как дополнение к tableView:editingStyleForRowAtIndexPath:. Метод tableView:canEditRowAtIndexPath: разрешает или запрещает действия над ячейкой в указанной в indexPath координате.


— (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row % 2 == 0) {
        return YES;
    } else {
        return NO;
    }
}

Фильтрация режима редактирования для части ячеек

Скачать архив (15Кб)

Удачи в создании своих приложений! :)

Комментарий

Комментарии

cDima 14.09.2020 9:53

Спасибо за отличный пост. Мне до сих пор таблицы кажутся в некотором виде вуду, но по-моему мы научились владеть ими на хорошом уровне. Круто.

ответить
Алексей Блинов 14.09.2020 14:04

Здóрово. Для полноты картины, наверное, надо было рассказать про перетаскивание строк.

ответить
Evgeniy Krysanov 15.09.2020 11:45

Для начала будет достаточно, чтобы не нагружать лишней информацией. Я руководствовался тем, что перетаскивание строк не самая часто употребимая функция.

ответить
Serjo 12.12.2020 12:42

Спасибо за отличный пост, Евгений. Есть вопрос, в режиме редактирования таблицы (удаление), после нажатия на иконку появляется кнопка Delete. Есть ли какая-нибудь стандартная возможность изменить текст на этой кнопке, например на Kill? Заранее спасибо за ответ.

ответить

Форма комментирования для «Режим редактирования таблиц»

Обязательное поле. Не больше 30 символов.

Обязательное поле

captcha image Пожалуйста, введите символы, которые вы видите на изображении

.