Содержание
Текст Домашнего Задания 4 на английском языке доступен на iTunes в пункте “Programming: Project 4: Smashtag Mentions″. На русском языке вы можете скачать здесь:
В Задании 4 вы должны усовершенствовать приложение Smashtag, которое мы создали на Лекции 9, чтобы обеспечить быстрый доступ к хэштэгам hashtags, URLs urls, изображениям images и пользователям users, упомянутым в твите. Основными идеями в этом Задании являются многопоточность, работа с таблицей Table View, глубокое знание Navigation Controller, множественные MVC типа Tab Bar Controller и работа с изображениями с помощью Scroll View.
Основой для решения Задания 4 является демонстрационный пример «Smashtag L9«, код которого доступен как на iTunes название “Lecture 9 Demo Code: Smashtag«, так и на Github.
Начало решения Задания 4 находится в посте Задание 4. CS193P Winter 2017. Smashtag Mentions (клиент Twitter). Решение — обязательные пункты 1- 7.
В данном посте представлено решение Обязательных пунктов 8 — 10 Задания 4.
Код для Обязательных пунктов 1- 7 находится на Github .
Код для Обязательных пунктов 1- 10 находится на Github.
Пункты 8 обязательный
Сохраняйте недавние 100 поисков в Twitter, которые пользователь выполнил в вашем приложении. Добавьте UITabBarController к вашему приложению с одной закладкой для поиска (то есть ваш главный UI) и второй закладкой, показывающей недавние поисковые термины, используемые для поиска в вашей таблице (они должны быть уникальны и первыми должны быть самые новые). Когда пользователь кликает на поисковом термине во второй закладке, “переезжайте” (segue) (оставаясь в той же самой закладке) куда-то, чтобы показать самые свежие твиты, соответствующие этому поисковому термину. Запомните эти недавно выполненные поисковые термины в постоянном хранилище, так чтобы ваше приложение не забывало их в случае повторного старта приложения.
В подсказке № 25 Задания 4 предлагается идея создания глобального “хранилища” для недавних поисковых терминов в UserDefaults.
Возможно, хорошая идея — иметь глобальное “хранилище” для недавних поисковых терминов, так как вам все равно нужно запоминать их в хранилище UserDefaults. Почему бы не сделать этим хранилищем UserDefaults? Вы можете создать маленький класс или структуру для хранения и извлечения данных из хранилища UserDefaults, которую можно использовать всюду в вашем приложении.
Мы создаем структуру RecentSearches, в которой использована идея работы с массивом, сохраняемым в UserDefaults, через вычисляемую переменную. В нашем случае public API для класса RecentSearches будет static массив поисковых строк searches: [String], который хранится в UserDefaults:
. . . . . . . . . . . . . . . .
Мы должны дополнить этот класс двумя static методами: один из них добавляет строку поиска в массив searches, удовлетворяя требованиям уникальности и временной актуальности добавляемой строки, другой должен уметь удалять элемент массива searches с определенным индексом index :
Добавлять строки поиска в хранилище RecentSearches.searches мы будем при задании поисковой строки searchText в классе TweetTableViewController :
А доставать из хранилища RecentSearches.searches мы будем в методе «жизненного цикла» viewDidLoad в классе TweetTableViewController при условии, что searchText не был установлен ранее в процессе подготовки к «переезду» на этот MVC:
Для второй закладки UITabBarController нужно построить MVC, показывающий недавние поисковые термины, используемые для поиска в вашей таблице твитов. Эти недавние поисковые термины находятся в хранилище RecentSearches.searches и мы можем их использовать для отображения в таблице. Перетягиваем Table View Controller из палитры объектов, создаем новый subclass UITableViewController, который назовем RecentTableViewController, и не забываем выставить этот класс на storyboard для вновь созданного Table View Controller. Эту операцию мы делали много раз, и я не буду на ней подробно останавливаться. Для таблицы недавних поисковых терминов public API — это массив поисковых строк recentSearches:
Как только нам становится известен массив recentSearches отображаемых данных в таблице, задача отображения сводится к реализации методов делегата dataSource, которые мы ниже представим. Но у этой таблице есть «изюминка». Дело в том, что этот массив нам никто не дает, а он хранится и постоянно обновляется в хранилище UserDefaults. Чтобы извлечь оттуда самые свежие данные, мы должны «перезагружать» таблицу при каждом новом появлении ее на экране. Это лучше всего делать в методе viewWillApear «жизненного цикла» View Controller, который содержит обращение к методу reloadData(), и заставит заработать методы делегата dataSource,опирается на Модель recentsSearches:
Когда пользователь кликает на поисковом термине во второй закладке, нас просят “переезжать” (segue) (оставаясь в той же самой закладке) на Table View Controller, чтобы показать самые свежие твиты, соответствующие этому поисковому термину. Это будет тот же самый Table View Controller, на который мы «переезжали» с таблицы меншенов в Обязательном пункте 5. Код для метода prepare (for seque:, sender:) тоже стандартный:
Вы можете провести отладку экранного фрагмента Recents без UITabBarController. Для этого вставляем экранный фрагмент Recents в Navigation Controller и перебрасываете на него маленькую стрелочку старта приложения.
С учетом добавления UITabBarController, storyboard будет выглядеть как представлено на рисунке ниже:
Запускаем приложение, в поисковой строке появляется введенная в прошлом сеансе поисковая строка «#вечер«, переходим на закладку Recents, там список введенных в прошлом сеансе поисковых строк, выбираем строку «#облака» и переходим назад, к MVC со списком твитов, но поисковая строка «#облака» уже установлена и поиск твитов осуществлен. Отсюда мы можем вернуться обратно на закладку Recents с помощью возвратной кнопки и выбрать другую поисковую строку:
Пункт 9 обязательный
Сетевые запросы никогда не должны блокировать main thread в вашем приложении.
К счастью, мы уже позаботились об этом. Метод fetchTweets класса TwitterRequest во фреймворке Twitter выполняет свой handler за пределами main thread. В ImageViewController использовалась многопоточная обработка, которая подробно объяснялась на Лекции 8. Загрузка изображение профайла tweetProfileImageView в пользовательском классе TweetTableViewCell для отображения твита в ячейке таблицы также происходит за пределами main queue на некоторой глобальной очереди . Для обновления изображения на UI мы возвращаемся обратно на main queue :
Отметим важность строки, выделенной синим цветом. Она позволяет предотвратить обработку данных, пришедших из сети и потерявших актуальность. Дело в том, что cells таблицы UITableView создаются только для видимых ячеек, и затем они используются повторно по мере того, как данные приходят на экран и уходят с экрана. Так что при скроллинге нашей таблицы твитов, данные о миниатюре могут подгрузиться, а сама ячейка уже «ушла» с экрана и нет смысла размещать ее на UI.
Эта функция используется при обновлении пользовательского интерфейса ячейки
Пункт 10 обязательный
Ваше приложение должно работать правильно как в портретном, так и в ландшафтном режимах на любом iPhone (это приложение только для iPhone).
Мы везде правильно использовали механизм Autolayout, поэтому выполнение этого пункта обеспечивается автоматически:
Код для Обязательных пунктов 1- 10 можно найти на Github.
Продолжение находится в посте Задание 4. CS193P Winter 2017. Smashtag Mentions (клиент Twitter). Решение — дополнительные пункты 1-5.