пятница, 16 октября 2015 г.

32. UITableView Part 2

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

Для дополнительной панели создадим контроллер навигации
    UINavigationController *navigationController=[[UINavigationController alloc] initWithRootViewController:controller];
    self.window.rootViewController=navigationController;

Инициализируем его нашим ранее созданным контроллером UIViewController и затем указываем, что главный контроллер для окна - navigationController.

У нас появляется дополнительная панель сверху.
В каждом View Controller есть объект navigationItem.
Чтобы задать заголовок для нашего контроллера

self.navigationItem.title=@"Students";

Для того, чтобы создать кнопку на навигационном контроллере
создаем системную кнопку edit и указываем обработчик событий actionEdit 

    UIBarButtonItem * editButton= [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(actionEdit:)];

Добавляем созданную кнопку на self.navigationItem

self.navigationItem.rightBarButtonItem=editButton;

Так выглядит обработчик события нажатия кнопки Edit

-(void) actionEdit:(UIBarButtonItem*) sender{
    BOOL isEditing=self.tableView.editing;
    [self.tableView  setEditing:!isEditing animated:YES];
    UIBarButtonSystemItem item=UIBarButtonSystemItemEdit;
    if (self.tableView.editing) {
        item=UIBarButtonSystemItemDone;
    }
    UIBarButtonItem * editButton= [[UIBarButtonItem alloc]initWithBarButtonSystemItem:item
                                                                               target:self
                                                                               action:@selector(actionEdit:)];
    //self.navigationItem.rightBarButtonItem=editButton;
    [self.navigationItem setRightBarButtonItem:editButton animated:YES];
  

Обработчик меняет режим редактирования таблицы (включает/отключает)  и меняет системную кнопку в зависимости от режима.

Кнопку удаления мы убрали из таблицы, но отступ слева в режиме редактирования все равно остается
Для того, чтобы  убрать этот отступ нужно переопределить метод UITableViewDelegate

- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
    return NO;
}

Аналогично кнопке Edit добавляем кнопку системную кнопку Add слева для добавления секций
    UIBarButtonItem * addButton= [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(actionAdd:)];
    self.navigationItem.leftBarButtonItem=addButton;

Обработчик нажатия Add

-(void) actionAdd:(UIBarButtonItem*) sender{
    TAGroup *group=[[TAGroup alloc ]init];
    group.name=[NSString stringWithFormat:@"Group %@",@(self.groupsArray.count+1)];
    
    NSMutableArray *array=[NSMutableArray array];
    for (int j=0; j<(arc4random()%3+1); j++) {
        [array addObject:[TAStudent randomStudent]];
    }
    group.students=array;
    NSInteger newSectionIndex=0;
    [self.groupsArray insertObject:group atIndex:newSectionIndex];
    
    NSIndexSet *insertSections=[NSIndexSet indexSetWithIndex:newSectionIndex];
    [self.tableView beginUpdates];
    [self.tableView insertSections:insertSections withRowAnimation:(self.groupsArray.count%2)?UITableViewRowAnimationLeft:UITableViewRowAnimationRight];
    [self.tableView endUpdates];
}

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

   [self.tableView beginUpdates];

    [self.tableView endUpdates];

Создаем на основе индекса NSIndexSet для вставки секции

    NSIndexSet *insertSections=[NSIndexSet indexSetWithIndex:newSectionIndex];

Вставляем в таблицу новую секцию с анимацией  различной анимацией 

       [self.tableView insertSections:insertSections withRowAnimation:(self.groupsArray.count%2)?UITableViewRowAnimationLeft:UITableViewRowAnimationRight];

Чтобы запретить слишком быстрое добавление (анимация не успевает и могут произойти какие-нибудь проблемы), мы можем добавить следующий блок который на 0.3 секунды перестает принимать события от интерфейса

    [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        if ([[UIApplication sharedApplication] isIgnoringInteractionEvents]) {
            [[UIApplication sharedApplication ]endIgnoringInteractionEvents];
        }
    });

Чтобы запретить перемещение строки например перед первой строкой (в первой строке располагается добавление студентов), нужно определить метод

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
    if (proposedDestinationIndexPath.row==0) {
        return sourceIndexPath;
    }
    else{
        return proposedDestinationIndexPath;
    }
}
Запрет добавлять в 0 ряд.

Для обработки нажатия (выделения) строки/ряда нужно определить метод

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

//снимаем выделение
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
//если нажата 0 строка (добавить студента)
    if (indexPath.row==0) {
        TAGroup *group=self.groupsArray[indexPath.section];
        NSMutableArray *array;
//если студентов в группе нет, инициазируем массив, если есть, то на основе него инициализируем
        if (group.students.count==0) {
            array=[NSMutableArray array];
        }
        else{
            array=[NSMutableArray arrayWithArray:group.students];

        }

        //Создаем и добавляем студента в группу

        TAStudent *student=[TAStudent randomStudent];
        [array insertObject:student atIndex:0];
        group.students=array;
//Начинаем  обновлять таблицу         
        [self.tableView beginUpdates];
//создаем новый indexpath куда будем добавлять строку

        NSIndexPath *newIndewxPath=[NSIndexPath indexPathForItem:1 inSection:indexPath.section];
//добавляем 
        [self.tableView insertRowsAtIndexPaths:@[newIndewxPath] withRowAnimation:UITableViewRowAnimationFade];
        [self.tableView endUpdates];

//задержка 0.3 секунды для завершения анимации

        [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            if ([[UIApplication sharedApplication] isIgnoringInteractionEvents]) {
                [[UIApplication sharedApplication ]endIgnoringInteractionEvents];
            }
        });
    }

}

Для срабатывания нажатия (выделения) во время редактирование необходимо установить проперти allowsSelectionDuringEditing в YES

    self.tableView.allowsSelectionDuringEditing=YES;

Для появления клавиши удаление на каждой строке кроме первой, меняем метод

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
    if (indexPath.row==0 ){
     return UITableViewCellEditingStyleNone;
    }
    else{
        return UITableViewCellEditingStyleDelete;
    }

}

Для изменения подписи на кнопке удаления определяем метод

- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
    return @"Remove";

}

Для определения действий кнопок подтверждений удаления, добавления  определяем метод 

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{

    if (editingStyle==UITableViewCellEditingStyleDelete) {
        TAGroup *group=self.groupsArray[indexPath.section];
        TAStudent *student=group.students[indexPath.row-1];
        NSMutableArray *array=[NSMutableArray arrayWithArray:group.students];
        [array removeObject:student];
        group.students=array;

        [self.tableView beginUpdates];
        NSIndexPath *newIndewxPath=[NSIndexPath indexPathForItem:indexPath.row inSection:indexPath.section];
        [self.tableView deleteRowsAtIndexPaths: @[newIndewxPath] withRowAnimation:UITableViewRowAnimationRight];
        [self.tableView endUpdates];
        [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            if ([[UIApplication sharedApplication] isIgnoringInteractionEvents]) {
                [[UIApplication sharedApplication ]endIgnoringInteractionEvents];
            }
        });
    }

}

Ссылка на исходники к уроку.

Выполняя домашнее задание задание для индивидуального дизайна заголовков секций используется следующий метод

- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0, 0CGRectGetWidth( tableView.frame), 18)];
    UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(10,5,CGRectGetWidth(tableView.frame), 18)];
    [label setFont:[UIFont boldSystemFontOfSize:16]];
    TAModel *model=self.arrayModel[section];
    [label setText:model.modelName];
    label.textColor=[UIColor whiteColor];
    label.textAlignment=NSTextAlignmentCenter;
    [view addSubview:label];
    [view setBackgroundColor:[UIColor grayColor]];
    return view;
}



Домашнее задание к уроку 31-32:

Ученик

1. Создайте контроллер с таблицей в коде без сторибордов.
2. Заполните таблицу данными на свое усмотрение
3. Объедините данные в группы (секции)

Студент.

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

Мастер.

6. Реализуйте удаление рядов

Супермен

7. Реализуйте механзм добавления секций и рядов на ваше усмотрение

Выполнены все задания

Ссылка на исходник домашнего задания 31-32 UITableView.

Комментариев нет:

Отправить комментарий