Задание 4. CS193P Winter 2015. Решение — обязательные пункты 1- 4.

Screen Shot 2015-07-14 at 8.43.44 AMТекст Домашнего задания на английском языке доступен на  iTunes в пункте “Developing iOS 8 app: Programming: Project 4″.  Текст Домашнего задания на русском  языке доступен на 

Задание 4 iOS 8.pdf

 Для выполнения этого Задания необходимо освоение  Лекции 9Лекции 10 и Лекции 11.
В этом посте подробно описывается выполнение обязательных пунктов 1-4.
Код для Swift 1.2 находится на Github. Код для Swift 2.0 находится на Github.

Пункт 1 обязательный

Усовершенствуйте приложение Smashtag, полученное на лекции, в части выделения  (разными цветами каждого)  hashtags, urls и user screen names, упомянутых в тексте твита (они известны как “mentions” — меншены). Заметьте, что эти mentions уже обнаружены для вас в каждом твите и представлены как [IndexedKeyword]s в классе Tweet в поставляемом коде Twitter.

Класс Tweet.swift обеспечивает нас всем необходимым – массивами структур [IndexedKeyword] для каждой категории меншенов (mentions) в конкретном твите.

Screen Shot 2015-07-06 at 7.33.36 PM

Нам остается создать палитру цветов для раскраски меншенов, объявить это свойство как public API для прототипа ячейки TweetTableViewCell

Screen Shot 2015-07-07 at 9.02.14 AM

а затем раскрасить меншены в специальном методе формирования текста твита

Screen Shot 2015-07-06 at 8.10.17 PM

с помощью класса NSMutableAttributedString, предварительно создав ему расширение для установки заданного цвета текста для заданного диапазона

Screen Shot 2015-07-06 at 8.25.05 PM

Обновление текста происходит в хорошо знакомом нам методе updateUI()

Screen Shot 2015-07-06 at 8.21.15 PM
.  .  .  .  .  .  .  .  .  .  .  .  .
Таким образом, мы не вы “не разрушили” preferred body фонт, используемый для показа твита.
Запускаем приложение  и получаем требуемый результат.

Screen Shot 2015-07-06 at 9.50.51 PM
Пункты 2, 3, 4 обязательные

  • Когда пользователь кликает на твите, “переезжайте” (segue) на новый UITableViewController, у которого 4 секции, показывающие “mentions” в твите: Images, URLsHashtags и Users.  Первая секция показывает (одно на строку) любые изображения, прикрепленные к твиту (найдены в переменной media в классе Tweet). Последние 3 секции показывают элементы, описанные в Обязательном пункте  №1 (опять, по одному на строку).
  • Каждая секция в таблице “mentions” должна иметь соответствующие заголовки.
  • Если в секции нет никаких элементов, то заголовок не должен быть виден для этой секции.

Добавляем из палитры объектов дополнительный Table View Controller на storyboard. В этой таблице нам будут нужны два прототипа ячеек таблицы: один для того, чтобы поместить туда строку URLs, Hashtags и Users, а другой прототип — для размещения изображений  Images.

Screen Shot 2015-07-07 at 8.36.14 AM
Один прототип — он имеет идентификатор Keyword Cell — это обычная табличная ячейка UITableViewCell, имеющая стиль Basic , который позволяет вывести на экран только заголовок Title, то есть разместить строку.

Другой прототип — он имеет идентификатор Image Cell — это ячейка,  настраиваемая пользователем, поэтому задаем ей стиль Custom. Для нее мы создадим специальный класс  ImageTableViewCell, который позволит загрузить в ячейку изображение. Изображение Image View нужно перетянуть из палитры объектов на storyboard в этот custom прототип ячейки и сделать все необходимые настройки для механизма Autolayout.

Screen Shot 2015-07-07 at 8.55.25 AM
Не забудьте создать специальный класс  ImageTableViewCell для нашей ячейки и установить его в Инспекторе Идентичности (Identity Inspector) для прототипа  Image Cell.

Screen Shot 2015-07-07 at 9.08.53 AM
Но вернемся к нашей таблице и создадим для нее специальный класс MentionsTableViewController, который является subclass UITableViewController и не забудем указать его в Инспекторе Идентичности (Identity Inspector) для нашей таблице на storyboard.

Screen Shot 2015-07-07 at 9.52.08 AM

Давайте подумаем, что является для нашего класс MentionsTableViewController public API. Согласно заданию эта таблица должна отображать меншены для определенного твита, следовательно сам твит и является public API класса MentionsTableViewController. То есть своего рода Моделью в терминологии паттерна проектирования MVC.
Screen Shot 2015-07-07 at 9.57.19 AM
Имея твит tweet, мы должны извлечь все меншены и отобразить их в таблице. Для отображения данных в таблице в подсказке № 7 Задания 4 нам предлагают создать внутреннюю структуру данных, которая бы собирала данные по секциям (учитывая их похожесть и различия) и очень просто работала бы с  UITableViewDataSource таблицы Table View.

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

Screen Shot 2015-07-07 at 10.58.43 AM

На верхнем уровне будет массив секций mentionTypes: [MentionType], представленных структурой MentionType, в которой задается тип секции type, который одновременно является и названием секции, и массив меншенов этого типа mentions : [Mention].

Каждый меншен представлен перечислением enum Mention, который включает в себя два варианта:

  • просто ключевое слово Keyword (String) c ассоциированным значением String в виде строки,
  • изображение Image (NSURL, Double) c ассоциированными значениями виде NSURL (где взять изображение) и  Double ( aspect ratio или соотношение сторон).

Первый вариант подходит для меншенов hashtagsurls и user screen names, а второй — для images. Имея такую структуру очень просто реализовать методы делегата UITableViewDataSource для таблицы.
Screen Shot 2015-07-07 at 11.28.17 AM
Особого внимания заслуживает последний метод cellForRowAtIndexPath, в котором используются два различных прототипа ячеек: обычный UITableViewCell для меншенов, представленных ключевым словом, и ImageTableViewCell для меншенов, представленных ключевым изображением.

Чтобы покончить с методами делегата Table View, примем к рассмотрению подсказки № 17 — 19 Задания 4.

17. Высота строки в вашем новом Сontroller не нуждается в “оценке” как высота строки в “списке твитов”, потому что у вас очень мало строк и производительность не играет решающего значения. Следовательно, вам захочется реализовать метод heightForRowAtIndexPath делегата UITableViewDelegate.

18. Для строк, содержащих изображение ( image), вам придется рассчитать подходящую высоту. Для других строк в вашей таблице вы можете позволить рассчитаться высоте строки автоматически (используя Autolayout) путем возврата UITableViewAutomaticDimension из метода heightForRowAtIndexPath.

19. Вы можете рассчитать соотношение сторон (aspect ratio) изображения (image) в твите, не прибегая к реальной выборки image из своего url. Смотри класс MediaItem в дополнительных Twitter классах.

Следуя этим рекомендациях получаем код для еще двух методов делегата Table View.
Screen Shot 2015-07-07 at 12.25.58 PM
Теперь осталась самая главная и интересная часть — загрузить нашу таблицу данными, а ведь у нас кроме твита tweet ничего нет в public API, поэтому следующая наша задача — преобразовать  tweet во внутреннюю структуру  mentionTypes: [MentionType], и сделать мы это должны как только кто-то извне установит нам значение переменной   tweet.
Screen Shot 2015-07-07 at 12.35.29 PM
Надо сказать, что этот код с точки зрения паттерна конструирования MVC выполняет типичную для Controller задачу — преобразование данных Модели в данные, требуемые View.
Осталось подсоединить вновь созданный Mentions Table View Controller к списку твитов Tweets Table View Controller, и мы сделаем это с помощью push segue от ячейки в таблице Tweets Table View Controller к таблице меншенов.
Screen Shot 2015-07-07 at 12.55.00 PM
Не забывайте указать идентификатор segue, он нам пригодится в коде. Мы задали идентификатор как Show Mentions и поместим его в специальную структуру в классе TweetsTableViewController.
Screen Shot 2015-07-07 at 1.09.22 PM
Еще нам нужно написать в этом же классе метод prepareForSegue:
Screen Shot 2015-07-07 at 1.11.51 PM
Именно в выделенной выше строке происходит использование public API класса MentionsTableViewController и именно она позволит запустит механизм загрузки таблицы меншенов.
Осталась еще одна и последняя маленькая деталь — это пользовательский класс ImageTableViewCell, обслуживающий прототип ячейки Image Cell, отображающей изображения. Для этого класса  public API будет URL местонахождения изображения в сети — imageURL: NSURL. Нам нужно закачать оттуда данные и отобразить в ячейке. Причем выполнить все это мы должны, не блокируя main queue. Это задача нам уже знакома по приложению Cassini, которое рассматривалось на Лекции 9, поэтому я не буду останавливаться подробно на описании кода.
Screen Shot 2015-07-07 at 1.30.44 PM
Запускаем приложение и смотрим вариант с изображением.
Screen Shot 2015-07-07 at 1.48.26 PM
Смотрим вариант без изображения — эта секция отсутствует.
Screen Shot 2015-07-07 at 1.50.28 PM
Проверим выполнение пункта № 20 в подсказках

20. Замечательной возможностью вашего приложения является (должно быть!) то, что если пользователь захочет увеличить немного масштаб изображения (image) в твите без того, чтобы кликать на нем и “переезжать” на MVC для подробного показа image, пользователь может просто перевернуть прибор в ландшафтный режим. Если все выполнено правильно, то вы получите эту возможность бесплатно (то есть не написав ни строчки кода).

Screen Shot 2015-07-14 at 8.32.36 AM

 

 

Код для Swift 1.2 находится на Github. Код для Swift 2.0 находится на Github.
Продолжение следует…

Задание 4. CS193P Winter 2015. Решение — обязательные пункты 1- 4.: 2 комментария

  1. Красиво получилось!! 🙂 Единственное, обратил внимание, что когда у твита есть значек фото или он отображается не полностью, то ссылка не подсвечивается синим.

Обсуждение закрыто.