[5] Дневник разработки AppleInsider.ru для iOS 7

Мы продолжаем рассказывать вам о том, как продвигается процесс разработки обновленной версии приложения AppleInsider.ru под iOS 7. Повествование ведет лично генеральный директор студии Unreal Mojo Слава Карпенко, поэтому интересное и информативное чтиво гарантировано. Сегодня мы предлагаем вам очередную запись этого дневника.

AppleInsider.ru для iOS 7

День 6

Или, скорее «шестой эпизод»

В прошлый раз остановился на том, что более-менее сделал общую работу с таблицей новостей, даже переписав процесс отображения пузырька с количеством комментариев. На следующий день обнаружил, что слегка облажался с подсчётом ширины этого самого пузырька — в формуле поставил плюс вместо минуса, в результате, чем «шире» было число, тем уже получался пузырёк. Исправил.

Далее подключил нотификации об изменениях состояния объектов, чтобы таблица должным образом обновлялась, когда, например, ты читаешь статью, или когда меняется количество комментариев к статье.

Поскольку первые две версии приложения работали с сервером по-другому, зачастую создавая лишнюю нагрузку, а также особенно из-за досадного ограничения архитектуры работы с сервером, если приложение не запускалось несколько дней, был шанс пропустить несколько статей, что вышли в то время, что вы его не запускали, методологию работы с серверным API было решено поменять.

Ранее (в AppleInsider.ru 1.x и 2.x) приложение запрашивало у сервера список последних опубликованных статей со всеми атрибутами (название, автор, дата, кол-во комментариев, ссылка на статью, ссылка на картинку и туча ещё всякого разного). Помимо того, что это жрало лишний трафик для пользователей, оно ещё и генерировало много избыточного трафика на сервере. Потому в версии 3 приложения было решено делать по-другому: теперь оно запрашивает только список идентификаторов статей с датой публикации, а затем, только если в базе нет остальных данных для каждой из требуемых статей, спрашивает сервер о данных для конкретных необходимых статей. Чтобы минимизировать нагрузку на сервер (а мы помним, что приложением пользуются десятки тысяч людей ежедневно), такие запросы также группируются приложением и высылаются пакетно: все запросы о получении информации о статье за прошедшую секунду собираются в кучу, и отправляются на сервер.

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

typedef enum { kPostInfo_Title = (1L << 1), kPostInfo_CommentCount = (1L << 2), kPostInfo_PostBody = (1L << 3), kPostInfo_Thumbnail = (1L << 4), kPostInfo_Slug = (1L << 5), kPostInfo_URL = (1L << 6), kPostInfo_Date = (1L << 7), kPostInfo_Metadata = (kPostInfo_Title | kPostInfo_CommentCount | kPostInfo_Thumbnail | kPostInfo_Slug | kPostInfo_URL | kPostInfo_Date)
} PostInfoMask;

Решив за несколько часов данные задачи и оттестирововав работу свеженаписанного кода, перешёл к следующей задаче: отображению картинок к статьям.

AppleInsider.ru для iOS 7

Для хранения картинок было решено использовать FastImageCache от Path. Решение было принято по многим причинам: хранить все скачанные картинки на диске в виде отдельных .jpg файлов, как было сделано в предыдущих версиях приложения — весьма дорого с точки зрения производительности, в результате, когда пользователь мотал вверх-вниз список новостей, на каждую ячейку приходилось загружать файл с диска, распаковывать его (он же JPEG) и только после этого рисовать. Конечно, ряд оптимизаций был и в прошлых версиях, но то, что предлагают ребята из Path, мне в целом понравилось больше.

Оставлю за скобками то, что я вообще очень хорошо отношусь к Path, так как их сооснователь Dustin Mierau когда-то начинал свою карьеру программиста в моей первой компании, помогая в разработке плеера MacAmp.

Где-то за час интегрировал библиотеку в код, заодно сразу написав код, который бы через UIBezierPath вырезал полученную картинку в кружочек, как в дизайне. Потом подключил код к сетевому менеджеру, который запрашивает картинки через вторую NSURLSession (с низким приоритетом выполнения) и всё магическим образом заработало:

AppleInsider.ru для iOS 7

Попутно нашел проблему — в заголовках статей встречаются HTML entities типа « — как на скриншоте выше в статье про «Генеральный директор». Добавил код, который транслирует их в обычный UTF-8 (при помощи куска GoogleToolboxMac).

Заодно обнаружил, что на сервере все «маленькие» картинки для статей хранятся в виде не совсем уж маленьких — зачастую размером под 100 килобайт и где-то 650 пикселей в ширину (тогда как приложению нужно максимум 140). Приложение, конечно, после скачивания картинку обрезает в нужный вид, но лишний траффик вроде как тоже не нужен. Посоветовался с ребятами, кто занимается для AppleInsider.ru серверной стороной, они постараются ужимать такие картинки на сервере в будущем. Отрадно то, что переделывать приложение для этого будет не нужно ☺

На этом работы по созданию списка новостей можно считать более-менее завершёнными. Для него останется сделать:

  1. Поиск — этим я займусь позже
  2. Шаринг в соцсети — этим я тоже займусь позже, после того, как сделаю контроллер для просмотра текста новости, которому будет нужен тот же самый шаринг
  3. Переключатель сверху Новости — Избранное — Категории. Его сделаю сразу после просмотра текста новости
  4. Реализовать показ рекламных баннеров.

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

AppleInsider.ru для iOS 7

Как и в предыдущих версиях, это, по сути, обёртка над UIWebView, так как текст статьи нам приходит в HTML. От обычного браузера контроллер отличается весьма сложной логикой работы с содержимым статьи.

Из старой версии взял код, который вставляет текст статьи в шаблон HTML, который в дальнейшем показывается в web view. Конечно, сам HTML и стили пришлось подточить, чтобы стало похоже на то, что нарисовал дизайнер (кое-где, он, конечно, нафантазировал такого, что я сделать не могу, но без этого никогда не обходится, потому всегда нужно искать разумные компромиссы или игнорировать мега-идеи ;).

Когда пользователь при чтении статьи касается картинки или ссылки, то включается умеренно разветвлённый алгоритм проверок на то, что же нужно сделать:

  • Если это картинка, то нужно показать её в отдельном контроллере на весь экран;
  • Если это ссылка на некую веб-страницу, то нужно понять, внешняя это ссылка или ссылка на статью на AppleInsider.ru;
  • Если ссылка внешняя, то посмотреть, допускается ли её открывать без вопросов пользователю о том, хочет ли он перейти по ней (там есть набор неких правил, по которым понятно, спрашивать или не спрашивать);
  • Если ссылка внутренняя, то посмотреть, является ли это ссылкой на статью с «буквенным» названием (например, https://appleinsider.ru/sluxi/sluxi-evad3rs-prodalis-kitajcam-za-million-dollarov.html — в ней такой «буквенной» частью будет «sluxi-evad3rs-prodalis-kitajcam-za-million-dollarov»). Сделать поиск по собственной базе в поисках этого тега для статей (вдруг её не надо загружать). Если ничего не нашлось, то спросить сервер о том, какой идентификатор принадлежит статье с таким названием, после чего загрузить данные и показать новый контроллер с этой статьей;
  • Если ссылка внутренняя, но вида https://appleinsider.ru/?p=241842, тогда получить из ссылки идентификатор (241842), далее поискать его в собственной базе, если нет, то спросить о ней сервер, далее загрузить данные и тоже показать статью.

Собрал, частично переписал код и вуаля!

AppleInsider.ru для iOS 7 AppleInsider.ru для iOS 7

После этого стал реализовывать логику перехода по ссылкам на статью и обнаружил, что сервер сломался и не возвращает необходимых данных (обычное дело для любого проекта, который взаимодействует с каким-либо сервером). Пока ребята там разбираются, буду заниматься другими вещами, благо работы хватает.

< Предыдущая запись

Обзоры приложений для iOS и MacРазработка приложений для iOS