Содержание
Текст Домашнего Задания 4 на английском языке доступен на iTunes в пункте “Programming: Project 4: Smashtag Mentions″. На русском языке вы можете скачать здесь:
Для выполнения Задания 4 необходим материал Лекции 8 и Лекции 9. Исходное приложение Smashtag L9 находится на сайте Стэнфорда для Xcode 7 и Swift 2.2. Если вы установили Xcode 8, то для Swift 2.3 код находится на Github, а для Swift 3 — также на Github.
Начало решения Задания 4 находится в посте Задание 4. CS193P Spring 2016. Smashtag Mentions (клиент Twitter). Решение — обязательные пункты 1- 7.
В данном посте представлено решение Обязательных пунктов 8 — 10 Задания 4.
Код для Обязательных пунктов 1- 7 находится на Github для Xcode 7 и Swift 2.2.
Код для Обязательных пунктов 1- 10 находится на Github для Xcode 7 и Swift 2.2.
Если вы установили Xcode 8, то для Swift 2.3 код находится на Github, а для Swift 3 — также на Github.
Пункты 8 обязательный
Сохраняйте недавние 100 поисков в Twitter, которые пользователь выполнил в вашем приложении. Добавьте UITabBarController к вашему приложению с одной закладкой для поиска (то есть ваш главный UI) и второй закладкой, показывающей недавние поисковые термины, используемые для поиска в вашей таблице (они должны быть уникальны и первыми должны быть самые новые). Когда пользователь кликает на поисковом термине во второй закладке, “переезжайте” (segue) (оставаясь в той же самой закладке) куда-то, чтобы показать самые свежие твиты, соответствующие этому поисковому термину. Запомните эти недавно выполненные поиски в постоянном хранилище NSUserDefaults так, чтобы ваше приложение не забывало их в случае повторного старта приложения.
В подсказке № 25 Задания 4 предлагается идея создания глобального “хранилища” для недавних поисковых терминов в NSUserDefaults. Мы создаем структуру RecentSearches, в которой использована идея работы с массивом, сохраняемым в NSUserDefaults, через вычисляемую переменную. В нашем случае public API для класса RecentSearches будет static массив строк searches: [String] недавнего поиска, который хранится в NSUserDefaults.
. . . . . . . . . . . . . . . .
Мы должны дополнить этот класс двумя static методами: один из них добавляет строку поиска в массив searches, удовлетворяя требованиям уникальности и временной актуальности добавляемой строки, другой должен уметь удалять элемент массива с определенным индексом.
Добавлять строки поиска мы будем при задании строки поиска searchText в классе TweetTableViewController :
Теперь мы можем использовать массив searches для отображения недавних поисковых терминов. Для этого перетягиваем Table View Controller из палитры объектов, создаем новый subclass UITableViewController, который назовем RecentTableViewController,и не забываем выставить этот класс на storyboard для вновь созданного Table View Controller. Эту операцию мы делали много раз, и я не буду на ней подробно останавливаться. Для таблицы недавних поисковых терминов public API является массив строк recentSearches недавних поисковых терминов:
Как только нам становится известен массив отображаемых данных в таблице, задача отображения сводится к реализации методов делегата dataSource, которые мы ниже представим. Но у этой таблице есть «изюминка». Дело в том, что этот массив нам никто не дает, а он постоянно обновляется в хранилище NSUserDefaults. Чтобы извлечь оттуда самые свежие данные, мы должны «перезагружать» таблицу при каждом новом появлении ее на экране. Это лучше всего делать в методе viewWillApear «жизненного цикла» View Controller, который содержит обращение к методу reloadData(), и заставит заработать
методы делегата dataSource,опирается на Модель recentsSearches :
Когда пользователь кликает на поисковом термине во второй закладке, нас просят “переезжать” (segue) (оставаясь в той же самой закладке) на Table View Controller, чтобы показать самые свежие твиты, соответствующие этому поисковому термину. Это будет тот же самый Table View Controller, на который мы «переезжали» с таблицы меншенов в Обязательном пункте 5. Код для метода prepareForSeque тоже стандартный:
Вы можете провести отладку экранного фрагмента Recents без UITabBarController. Для этого вставляем экранный фрагмент Recents в Navigation Controller и перебрасываете на него маленькую стрелочку страта приложения.
С учетом добавления UITabBarController, storyboard будет выглядеть как представлено на рисунках. Оказалось, что storyboard трудно уместить на одном рисунке. Поэтому она показана на двух рисунках с небольшим смещение влево.
Пункт 9 обязательный
Сетевые запросы никогда не должны блокировать main thread в вашем приложении.
К счастью, мы уже позаботились об этом. Метод fetchTweets класса TwitterRequest выполняет свой handler за пределами main thread. В ImageViewController использовалась многопоточная обработка, которая подробно объяснялась на Лекции 8. Однако загрузка миниатюры tweetProfileImageView в пользовательском классе TweetTableViewCell для отображения твита в ячейке таблицы все еще происходит с блокировкой main queue. Добавим специальную функцию для загрузки этого изображения в параллельной очереди, как мы поступили при загрузке изображения в классе ImageViewController :
Отметим важность строки, выделенной синим цветом. Он позволяет предотвратить обработку данных, пришедших из сети и потерявших актуальность. Дело в том, что cells таблицы UITableView создаются только для видимых ячеек, и затем они используются повторно по мере того, как данные приходят на экран и уходят с экрана. Так что при скроллинге нашей таблицы твитов, данные о миниатюре могут подгрузиться, а сама ячейка уже «ушла» с экрана и нет смысла размещать ее на UI.
Эта функция используется при обновлении пользовательского интерфейса ячейки
Пункт 10 обязательный
Ваше приложение должно работать правильно как в портретном, так и в ландшафтном режимах на любом iPhone (это приложение только для iPhone).
Мы везде правильно использовали механизм Autolayout, поэтому выполнение этого пункта обеспечивается автоматически.
Код для Обязательных пунктов 1- 10 можно найти на Github для Xcode 7 и Swift 2.2. Если вы установили Xcode 8, то для Swift 2.3 код находится на Github, а для Swift 3 — также на Github.
Продолжение в посте Задание 4. CS193P Spring 2016. Smashtag Mentions (клиент Twitter). Решение — дополнительные пункты 1-5.
Здравствуйте!
При использовании вычисляемой переменной выходит, что каждый раз при обращении к recentSearches в функции tableView(_, _) -> UITableViewCell контроллера RecentTableViewController мы обращаемся к NSUserDefaults.standardUserDefaults()? Правильно ли это? Не проще ли использовать не вычисляемую переменную, а обычную, просто инициализируемую в том же ViewDidLoad() или ViewWillAppear()? Заранее благодарю.
Я не очень понимаю, о чем вы говорите.
Ведь в структуре RecentSearches определена константа, которая вычисляется один раз (static):
private static let defaults = NSUserDefaults.standardUserDefaults()?
Если вы хотите такую константу получить в RecentTableViewControlle, то задавайте ее непосредственно там:
let defaults = NSUserDefaults.standardUserDefaults()?
А причем здесь ViewDidLoad() или ViewWillAppear()?
К сожалению, я ошибочно полагал, что метод synchronize() вызывается каждый раз при обращении к объекту класса NSUserDefaults. Прошу прощения.
Находясь на странице: https://bestkora.com/IosDeveloper/ios-9-swift-2-0/ при нажатии на пункт с решением обязательных заданий 8-10, открывается эта страница: https://bestkora.com/IosDeveloper/zadanie-4-cs193p-winter-2016-reshenie-obyazatelnye-punkty-1-4/
Спасибо. Исправлено.