Your SlideShare is downloading. ×
Алексей Патосин "Как можно доработать UITableViewController, чтобы облегчить себе жизнь"
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

348
views

Published on

Yandex Mobile Camp в Санкт-Петербурге, 30 мая 2012 …

Yandex Mobile Camp в Санкт-Петербурге, 30 мая 2012

Алексей Патосин, iOS-разработчик, Yota Lab.

Тема: Как можно доработать UITableViewController, чтобы облегчить себе жизнь

Тезисы:

Рассмотрим проблемы, с которыми сталкивался каждый, работая с таблицами в Cocoa Touch.

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


0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
348
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Yandex Mobile Camp Санкт-ПетербургКак можно доработать UITableViewController чтобы облегчить себе жизнь Патосин Алексей YotaLab
  • 2. Agenda1. Проблемы работы с таблицами под iOS2. У нас есть решение3. We need to go deeper 1
  • 3. Давайте поговорим о Cocoa таблицах
  • 4. Таблицы вокруг нас 3
  • 5. Какие бывают таблицы?1. Списки однородных элементов 2. Формы (1-... сущностей) (всё не так страшно) (сейчас немного поковыряем) 4
  • 6. Сложные формы Ночной кошмар, если таблица динамическаяПоказывать всегда Показывать всегдаТелефон +7(800)123-666-7 Телефон +7(800)123-666-7Email steve@apple.com Email steve@apple.comДобавить поле Добавить полеСейчас онлайн Сейчас онлайн Ringo Star Ringo Star Jimmy Page 5 мин5 мин 10 мин10 мин 15 мин15 мин ПолчасаПолчаса Если выбрано 15 минут и больше, то тут появляется этот текст 5
  • 7. Типичные способы управления сложной таблицей – Гроздь switch/case – State machine – Разруливание вариантов гроздями наследников 6
  • 8. Минусы использования UITableViewController (обо что спотыкался каждый)– Настройка таблиц через UITableViewControllerDelegate (хочется задать все параметры в конструкторе/билдере)– Заполнение и обновление таблицы через UITableViewControllerDataSource (мы ненавидим indexPath)– Работа с ячейкой (ячейка “не знает”, что на неё нажали) 7
  • 9. Чего хочется?
  • 10. Чего хочется?– Абстрагироваться от работы с таблицей и работать сданными– Хочется, чтобы таблица стала более “smart” - таблица знала когда себя обновлять - ячейки знали когда себя обновлять - модель знала, что происходит в ячейках– Хочется реинвентить дата биндинг под iOS 9
  • 11. “smart” ячейка таблицыХочется, чтобы ячейка стала самостоятельнымэлементом и знала: 10
  • 12. “smart” ячейка таблицыХочется, чтобы ячейка стала самостоятельнымэлементом и знала: model view +7 800 123 6667 что показывать (model > view) 10
  • 13. “smart” ячейка таблицыХочется, чтобы ячейка стала самостоятельнымэлементом и знала: model view +7 800 123 что обновлять (view changed > model changed) model view +7 800 123 6667 10
  • 14. “smart” ячейка таблицыХочется, чтобы ячейка стала самостоятельнымэлементом и знала: view model +7 800 123 4567 когда обновлять (model changed > view changed) model view model view +7 800 123 6667 +7 800 123 10
  • 15. Houston, we have a solution
  • 16. Структура таблицыLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.AbraCadabraCarambaLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer. 12
  • 17. Структура таблицы sectionLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.AbraCadabraCarambaLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer. 12
  • 18. Структура таблицы sectionLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer.Abra CadabraCarambaLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer. 12
  • 19. Структура таблицы sectionLorem ipsum dolor sit amet, consectetuer cells adipiscing elit. Aenean consectetuer.Abra CadabraCarambaLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean consectetuer. 12
  • 20. Структура таблицы sectionLorem ipsum dolor sit amet, consectetuer cells adipiscing elit. Aenean consectetuer.Abra headerTitle Cadabra headerViewCaramba headerHeightLorem ipsum dolor sit amet, consectetuer footerTitle adipiscing elit. Aenean consectetuer. footerView footerHeight 12
  • 21. Структура таблицы sectionLorem ipsum dolor sit amet, consectetuer cells adipiscing elit. Aenean consectetuer.Abra headerTitle Cadabra headerViewCaramba headerHeightLorem ipsum dolor sit amet, consectetuer footerTitle adipiscing elit. Aenean consectetuer. footerView footerHeight 12
  • 22. Структура таблицы sectionLorem ipsum dolor sit amet, consectetuer cells cellActions adipiscing elit. Aenean consectetuer.Abra headerTitle Cadabra headerViewCaramba headerHeightLorem ipsum dolor sit amet, consectetuer footerTitle adipiscing elit. Aenean consectetuer. footerView footerHeight 12
  • 23. Мы выделили следующие типы ячеек 13
  • 24. Мы выделили следующие типы ячеек– Push Добавить поле– State - Switch Показывать всегда - Check 10 мин– Edit Email steve@apple.com - Flexible edit Телефон +7(800)123-666-7– Text Сейчас онлайн 12/32 13
  • 25. SmartTableViewController UITableViewController UITableViewControllerDelegate UITableViewControllerDataSourceSmartTableViewController UITableViewCell TableSectionContainer AbstractSmartTableViewCell PushTableViewCell TextTableViewCell EditTableViewCell AbstractStateTableViewCell FlexibleEditTableViewCell SwitchTableViewCell CheckTableViewCell 14
  • 26. Какая главная особенность “smart” ячейки?При создании ячейки действие задаётся через блок     [cell setCalledBlock:^{         NSLog(@"Hello there..");     }];Действия: - нажатие на ячейке - нажатие на переключателе - ввод текста в ячейке accessoryType появляется автоматически, если задан calledBlock 15
  • 27. Какие вкусности есть у “smart” таблицы? Оптимизированная работа с нотификациями NSNotification с использованием блока    [self addNotificationObserver:@"NotificationName"  object:_jet  usingBlock:^(NSNotification *notification){         //do smth     } calledBlockImmediately:YES]; (сейчас увидим как это работает) 16
  • 28. Какие вкусности есть у “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
  • 29. Как заполнять структуру таблицы- (void)updateSections{    [super updateSections];        [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];} 18
  • 30. Как заполнять структуру таблицы- (void)updateSections{    [super updateSections];         [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];} 18
  • 31. Как заполнять структуру таблицы- (void)updateSections{    [super updateSections];         [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];} 18
  • 32. Как заполнять структуру таблицы- (void)updateSections{    [super updateSections];         [sections addObject:[self pilotSection]];    [sections addObject:[self jetSection]];    [sections addObject:[self weaponSection]];         [self.tableView reloadData];} 18
  • 33. Как создавать секции- (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;} 19
  • 34. Как создавать секции- (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;} 19
  • 35. Как создавать секции- (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;} 19
  • 36. Как создавать секции- (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;} 19
  • 37. Как создавать секции- (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;} 19
  • 38. Как создавать ячейки- (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
  • 39. Как создавать ячейки- (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
  • 40. Как создавать ячейки- (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
  • 41. Как создавать ячейки- (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
  • 42. Как создавать ячейки- (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
  • 43. Как создавать ячейки- (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
  • 44. Как создавать ячейки- (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
  • 45. Некоторые нюансы специфичных ячеекStateTableViewCell и её потомки Check и Switch [cell setCalledBlock:^{      bself.jet.isOn = ! bself.jet.isOn;  }]; 21
  • 46. Некоторые нюансы специфичных ячеекEditTableViewCell     [cell setCalledBlock:^{         bself.jet.pilotName = cell.valueTextField.text;          }]; 22
  • 47. Некоторые нюансы специфичных ячеек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
  • 48. Что есть ещё?Ячейка помимо блоков может использовать классическуюконструкцию delegate, selector, object1, object2 cell.delegate = self; cell.selector = @selector(doSmth:); cell.object1ToAction = obj; 24
  • 49. Что есть ещё?Ячейка может на событие вызывать viewController имякоторого задано при её создании cell.viewControllerNameForPush = @”PilotViewController”; 25
  • 50. Что есть ещё?Таблица содержит гибкий механизм обновления секций и ячеек insertSection:atIndex: insertCell:inSection:atIndex: insertCells:inSection:atIndex: removeSection: removeCell:inSection: replaceSection:withSection: replaceCell:inSection:withCell: replaceSectionWithArrayOfSections: (для обращения к нужной секции или ячейки используется её уникальный идентификатор, задаваемый при создании) 26
  • 51. Thank you!alexey.patosin.rualexey@patosin.ru@gn0meavpSmartTableViewController:http://bit.ly/N8hcMe