51
Как можно доработать UITableViewController чтобы облегчить себе жизнь Патосин Алексей YotaLab Yandex Mobile Camp Санкт-Петербург

Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

  • Upload
    yandex

  • View
    375

  • Download
    0

Embed Size (px)

DESCRIPTION

Yandex Mobile Camp в Санкт-Петербурге, 30 мая 2012Алексей Патосин, iOS-разработчик, Yota Lab.Тема: Как можно доработать UITableViewController, чтобы облегчить себе жизньТезисы: Рассмотрим проблемы, с которыми сталкивался каждый, работая с таблицами в Cocoa Touch. Как можно улучшить существующий подход, как элегантно избавиться от «копипасты» и сфокусироваться только на том, какие данные и в какой структуре показывать. Разработанный подход позволяет свести написание кода при создании таких таблиц и форм к минимуму.

Citation preview

Page 1: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как можно доработать UITableViewController

чтобы облегчить себе жизнь

Патосин АлексейYotaLab

Yandex Mobile Camp Санкт-Петербург

Page 2: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Agenda1. Проблемы работы с таблицами под iOS

2. У нас есть решение

3. We need to go deeper

1

Page 3: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Давайте поговорим о Cocoa таблицах

Page 4: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Таблицы вокруг нас

3

Page 5: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Какие бывают таблицы?

1. Списки однородных элементов 2. Формы (1-... сущностей)

(всё не так страшно) (сейчас немного поковыряем)

4

Page 6: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Сложные формы

Ночной кошмар, если таблица динамическая

Показывать всегда

Телефон +7(800)123-666-7

Email [email protected]

Добавить поле

Сейчас онлайн

Ringo Star

5 мин

10 мин

15 мин

Полчаса

Jimmy Page

Показывать всегда

Телефон +7(800)123-666-7

Email [email protected]

Добавить поле

Сейчас онлайн

5 мин

10 мин

15 мин

Полчаса

Ringo Star

Если выбрано 15 минут и больше,то тут появляется этот текст

5

Page 7: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Типичные способы управления сложной таблицей

– Гроздь switch/case

– State machine

– Разруливание вариантов гроздями наследников

6

Page 8: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Минусы использования UITableViewController

(обо что спотыкался каждый)

– Настройка таблиц через UITableViewControllerDelegate

– Заполнение и обновление таблицы через UITableViewControllerDataSource

– Работа с ячейкой

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

(мы ненавидим indexPath)

(ячейка “не знает”, что на неё нажали)

7

Page 9: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Чего хочется?

Page 10: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Чего хочется?

– Абстрагироваться от работы с таблицей и работать с данными

– Хочется, чтобы таблица стала более “smart” - таблица знала когда себя обновлять - ячейки знали когда себя обновлять - модель знала, что происходит в ячейках

– Хочется реинвентить дата биндинг под iOS

9

Page 11: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

“smart” ячейка таблицы

Хочется, чтобы ячейка стала самостоятельным элементом и знала:

10

Page 12: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

“smart” ячейка таблицы

Хочется, чтобы ячейка стала самостоятельным элементом и знала:

model view

+7 800 123 6667

что показывать (model > view)

10

Page 13: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

“smart” ячейка таблицы

Хочется, чтобы ячейка стала самостоятельным элементом и знала:

model view

+7 800 123 6667

model view

+7 800 123

что обновлять (view changed > model changed)

10

Page 14: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

“smart” ячейка таблицы

Хочется, чтобы ячейка стала самостоятельным элементом и знала:

model view

+7 800 123 6667

model view

+7 800 123

model view

+7 800 123 4567

когда обновлять (model changed > view changed)

10

Page 15: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Houston, we have a solution

Page 16: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Структура таблицы

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Abra

Cadabra

Caramba

12

Page 17: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Структура таблицы

sectionLorem ipsum dolor sit amet, consectetuer

adipiscing elit. Aenean consectetuer.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Abra

Cadabra

Caramba

12

Page 18: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Структура таблицы

sectionLorem ipsum dolor sit amet, consectetuer

adipiscing elit. Aenean consectetuer.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Abra

Cadabra

Caramba

12

Page 19: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Структура таблицы

sectioncellsLorem ipsum dolor sit amet, consectetuer

adipiscing elit. Aenean consectetuer.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Abra

Cadabra

Caramba

12

Page 20: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Структура таблицы

sectioncells

headerTitleheaderViewheaderHeightfooterTitlefooterViewfooterHeight

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Abra

Cadabra

Caramba

12

Page 21: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Структура таблицы

sectioncells

headerTitleheaderViewheaderHeightfooterTitlefooterViewfooterHeight

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Abra

Cadabra

Caramba

12

Page 22: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Структура таблицы

sectioncells

cellActionsheaderTitleheaderViewheaderHeightfooterTitlefooterViewfooterHeight

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.

Abra

Cadabra

Caramba

12

Page 23: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Мы выделили следующие типы ячеек

13

Page 24: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Мы выделили следующие типы ячеек

– Push

– State- Switch- Check

– Edit- Flexible edit

– Text

Добавить поле

Показывать всегда

10 мин

Email [email protected]

Сейчас онлайн

Телефон +7(800)123-666-7

12/32

13

Page 25: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

SmartTableViewController

UITableViewController UITableViewControllerDelegate

UITableViewControllerDataSource

SmartTableViewController

TableSectionContainer

UITableViewCell

AbstractSmartTableViewCell

PushTableViewCell

AbstractStateTableViewCell

CheckTableViewCellSwitchTableViewCell

TextTableViewCell

EditTableViewCell

FlexibleEditTableViewCell

14

Page 26: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Какая главная особенность “smart” ячейки?

При создании ячейки действие задаётся через блок

Действия:- нажатие на ячейке- нажатие на переключателе- ввод текста в ячейке

    [cell setCalledBlock:^{        NSLog(@"Hello there..");    }];

accessoryType появляется автоматически, если задан calledBlock 15

Page 27: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Какие вкусности есть у “smart” таблицы?

Оптимизированная работа с нотификациями NSNotification с использованием блока

    [self addNotificationObserver:@"NotificationName"  object:_jet  usingBlock:^(NSNotification *notification){

        //do smth    } calledBlockImmediately:YES];

(сейчас увидим как это работает) 16

Page 28: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Какие вкусности есть у “smart” таблицы?

Нотификации очищаются самостоятельно, если не нужна другая логика

- (void) removeNotificationObservers{  [_notifications enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {      [[NSNotificationCenter defaultCenter] removeObserver:obj];  }];  [_notifications removeAllObjects];}

- (void) dealloc{     [self removeNotificationObservers];  [_notifications release];      [super dealloc];}

нотификации храняться в словаре, следовательно один инстанс viewController не может хранить несколько нотификаций с одинаковыми именами 17

Page 29: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как заполнять структуру таблицы

- (void)updateSections{    [super updateSections];        [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];}

18

Page 30: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как заполнять структуру таблицы

- (void)updateSections{    [super updateSections];

        [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];}

18

Page 31: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как заполнять структуру таблицы

- (void)updateSections{    [super updateSections];

        [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];}

18

Page 32: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как заполнять структуру таблицы

- (void)updateSections{    [super updateSections];

        [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];}

18

Page 33: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать секции

19

- (TableSectionContainer *)pilotSection{    TableSectionContainer *section = [TableSectionContainer sectionWithSectionId:pilotSectionId];        section.headerTitle = @"Pilot";            [section.cells addObject:[self pilotCell]];        [section setFooterTitle:@"pilot name and range are required"];    [section setFooterHeight:20];              return section;}

Page 34: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать секции

19

- (TableSectionContainer *)pilotSection{    TableSectionContainer *section = [TableSectionContainer sectionWithSectionId:pilotSectionId];        section.headerTitle = @"Pilot";            [section.cells addObject:[self pilotCell]];        [section setFooterTitle:@"pilot name and range are required"];    [section setFooterHeight:20];              return section;}

Page 35: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать секции

19

- (TableSectionContainer *)pilotSection{    TableSectionContainer *section = [TableSectionContainer sectionWithSectionId:pilotSectionId];        section.headerTitle = @"Pilot";            [section.cells addObject:[self pilotCell]];        [section setFooterTitle:@"pilot name and range are required"];    [section setFooterHeight:20];              return section;}

Page 36: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать секции

19

- (TableSectionContainer *)pilotSection{    TableSectionContainer *section = [TableSectionContainer sectionWithSectionId:pilotSectionId];        section.headerTitle = @"Pilot";            [section.cells addObject:[self pilotCell]];        [section setFooterTitle:@"pilot name and range are required"];    [section setFooterHeight:20];              return section;}

Page 37: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать секции

19

- (TableSectionContainer *)pilotSection{    TableSectionContainer *section = [TableSectionContainer sectionWithSectionId:pilotSectionId];        section.headerTitle = @"Pilot";            [section.cells addObject:[self pilotCell]];        [section setFooterTitle:@"pilot name and range are required"];    [section setFooterHeight:20];              return section;}

Page 38: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать ячейки

- (PushTableViewCell *)pilotCell{    PushTableViewCell *cell = [PushTableViewCell cellWithCellId:pilotCellId];        __block typeof(self) bself = self;        [cell setCalledBlock:^{        [bself showPilotViewController];    }];        [self addNotificationObserver:@"PilotNameChanged" object:_jet.pilot  usingBlock: ^(NSNotification *notification){  cell.textLabel.text = [NSString  stringWithFormat:@"%@ %@", bself.jet.pilot.pilotName, [bself.jet.pilot pilotRangeDescription]];      } calledBlockImmediately:YES];        return cell;}

20

Page 39: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать ячейки

20

- (PushTableViewCell *)pilotCell{    PushTableViewCell *cell = [PushTableViewCell cellWithCellId:pilotCellId];        __block typeof(self) bself = self;        [cell setCalledBlock:^{        [bself showPilotViewController];    }];        [self addNotificationObserver:@"PilotNameChanged" object:_jet.pilot  usingBlock: ^(NSNotification *notification){  cell.textLabel.text = [NSString  stringWithFormat:@"%@ %@", bself.jet.pilot.pilotName, [bself.jet.pilot pilotRangeDescription]];      } calledBlockImmediately:YES];        return cell;}

Page 40: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать ячейки

20

- (PushTableViewCell *)pilotCell{    PushTableViewCell *cell = [PushTableViewCell cellWithCellId:pilotCellId];        __block typeof(self) bself = self;        [cell setCalledBlock:^{        [bself showPilotViewController];    }];        [self addNotificationObserver:@"PilotNameChanged" object:_jet.pilot  usingBlock: ^(NSNotification *notification){  cell.textLabel.text = [NSString  stringWithFormat:@"%@ %@", bself.jet.pilot.pilotName, [bself.jet.pilot pilotRangeDescription]];      } calledBlockImmediately:YES];        return cell;}

Page 41: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать ячейки

20

- (PushTableViewCell *)pilotCell{    PushTableViewCell *cell = [PushTableViewCell cellWithCellId:pilotCellId];        __block typeof(self) bself = self;        [cell setCalledBlock:^{        [bself showPilotViewController];    }];        [self addNotificationObserver:@"PilotNameChanged" object:_jet.pilot  usingBlock: ^(NSNotification *notification){  cell.textLabel.text = [NSString  stringWithFormat:@"%@ %@", bself.jet.pilot.pilotName, [bself.jet.pilot pilotRangeDescription]];      } calledBlockImmediately:YES];        return cell;}

Page 42: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать ячейки

20

- (PushTableViewCell *)pilotCell{    PushTableViewCell *cell = [PushTableViewCell cellWithCellId:pilotCellId];        __block typeof(self) bself = self;        [cell setCalledBlock:^{        [bself showPilotViewController];    }];        [self addNotificationObserver:@"PilotNameChanged" object:_jet.pilot  usingBlock: ^(NSNotification *notification){  cell.textLabel.text = [NSString  stringWithFormat:@"%@ %@", bself.jet.pilot.pilotName, [bself.jet.pilot pilotRangeDescription]];      } calledBlockImmediately:YES];        return cell;}

Page 43: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать ячейки

20

- (PushTableViewCell *)pilotCell{    PushTableViewCell *cell = [PushTableViewCell cellWithCellId:pilotCellId];        __block typeof(self) bself = self;        [cell setCalledBlock:^{        [bself showPilotViewController];    }];        [self addNotificationObserver:@"PilotNameChanged" object:_jet.pilot  usingBlock: ^(NSNotification *notification){  cell.textLabel.text = [NSString  stringWithFormat:@"%@ %@", bself.jet.pilot.pilotName, [bself.jet.pilot pilotRangeDescription]];      } calledBlockImmediately:YES];        return cell;}

Page 44: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Как создавать ячейки

20

- (PushTableViewCell *)pilotCell{    PushTableViewCell *cell = [PushTableViewCell cellWithCellId:pilotCellId];        __block typeof(self) bself = self;        [cell setCalledBlock:^{        [bself showPilotViewController];    }];        [self addNotificationObserver:@"PilotNameChanged" object:_jet.pilot  usingBlock: ^(NSNotification *notification){  cell.textLabel.text = [NSString  stringWithFormat:@"%@ %@", bself.jet.pilot.pilotName, [bself.jet.pilot pilotRangeDescription]];      } calledBlockImmediately:YES];        return cell;}

Page 45: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Некоторые нюансы специфичных ячеек

StateTableViewCell и её потомки Check и Switch

[cell setCalledBlock:^{     bself.jet.isOn = ! bself.jet.isOn; }];

21

Page 46: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Некоторые нюансы специфичных ячеек

    [cell setCalledBlock:^{        bself.jet.pilotName = cell.valueTextField.text;          }];

EditTableViewCell

22

Page 47: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Некоторые нюансы специфичных ячеек

FlexibleEditTableViewCell

typedef void(^CalledBlock)(void);typedef BOOL(^ShouldChangeCharactersInRange)(NSRange range, NSString *string);typedef BOOL(^TextFieldShouldReturnBlock)(void);typedef BOOL(^TextFieldShouldClearBlock)(void);

ShouldChangeCharactersInRange _shouldChangeCharactersInRangeBlock;TextFieldShouldReturnBlock _textFieldShouldReturnBlock;TextFieldShouldClearBlock _textFieldShouldClearBlock;CalledBlock _textFieldDidBeginEditingBlock;CalledBlock _textFieldDidEndEditingBlock;

23

Page 48: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Что есть ещё?

Ячейка помимо блоков может использовать классическую конструкцию delegate, selector, object1, object2

cell.delegate = self;cell.selector = @selector(doSmth:);cell.object1ToAction = obj;

24

Page 49: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Что есть ещё?

Ячейка может на событие вызывать viewController имя которого задано при её создании

cell.viewControllerNameForPush = @”PilotViewController”;

25

Page 50: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Что есть ещё?

Таблица содержит гибкий механизм обновления секций и ячеек

insertSection:atIndex:insertCell:inSection:atIndex:insertCells:inSection:atIndex:removeSection:removeCell:inSection:replaceSection:withSection:replaceCell:inSection:withCell:replaceSectionWithArrayOfSections:

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

26

Page 51: Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"

Thank you!

[email protected]@gn0meavp

SmartTableViewController :http://bit.ly/N8hcMe