Alamofire на примере

Пример использования библиотеки Alamofire

Задача: создать iOS приложение в среде разработки Xcode 9 на языке программирования Swift 4, которое посылает HTTP запрос, а в ответ получает данные, которые обрабатывает и отображает в виде таблицы. После разработки у нас получится такое приложение.

Для запроса данных мы будем использовать стороннюю библиотеку Alamofire. Alamofire — это свободно распространяемая, библиотека с открытым исходным кодом, благодаря которой работа с сетью (любые запросы, отправка и получения файлов, скачивание картинок и пр.) упрощается до написания нескольких строк. Думаю, если вы пытались разрабатывать iOS приложения, в которых используются стандартные классы от Apple, особенно, если вы  начинающий программист, — вы были немного озадачены набором классов и надстроек для совершения простого GET запроса. С помощью Alamofire код становится более элегантный и понятный для чтения.

Добавление Alamofire в проект

Я не буду подробно останавливаться на процессе добавления сторонних библиотек при помощи Cocoapods, однако если читатели в комментариях укажут, что скриншотов, которые следуют ниже, не достаточно, то я сделаю отдельный пост.

По шагам это выглядит так:

  • Добавьте в проект пустой файл и назовите его Podfile
  • Добавьте содержимое во вновь созданный файл:

  • Закройте Xcode
  • Откройте Terminal и перейдите в каталог с проектом
  • Наберите команду pod install (Все должно получится, если у вас в системе установлен Cocoapods. Если нет, то на официальном https://cocoapods.org сайте можно найти инструкцию по установке
  • После завершения скачивания библиотеки Alamofire в каталоге с проекта появится файл с названием вашего проекта, но расширение у него будет xworkspace. Сейчас и далее для работы с проектом в Xcode  нужно запускать и загружать именно этот файл.

Добавление кнопки в проект

Из библиотеки объектов перетащите кнопку на контроллер, задайте этой кнопке нужные цвета, размеры и ограничения. Создайте для кнопки соответствующий метод в контроллере, который будет вызываться при нажатии на эту кнопку. У меня получилось так:

В класс ViewController добавьте строку с импортом Alamofire

Теперь добавьте код в только что созданный метод:

Внимательно посмотрите на этот код. По сути, вся работа с сетью уложилась в одну строку. Давайте разбирать по частям, а первую строку методы мы тоже раздробим для понимания. Итак, у класса Alamofire есть метод request, который в качестве параметров принимает адрес, по которому следует послать запрос. (Кстати, адрес ссылается на сервис, который генерирует ответы на запросы. Этот сервис создан специально для разработчиков. Он возвращает структурированные данные, с которыми можно работать.) Этот метод принимает еще четыре параметра, с помощью которых можно кастомизировать запрос (изменить метод запроса, параметры, заголовки и кодировку), но для нашей задачи нам это не нужно и мы не будем это использовать.

Однако следует сказать, что при таком создании запроса по умолчанию устанавливается метод GET. Эту строку можно было записать по-другому:

Эти два примера будут работать одинаково. Думаю, понятно как изменить метод, если понадобится.

Под капотом Alamofire этот метод возвращает объект DataRequest. Мы к нему моем применить метод responseJSON. Этот метод преобразует полученные данные в запросе в массив объектов, с которыми мы будем работать позже.

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

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

Я не сомневаюсь, что для новичков это сложно для понимания. Но осознание функционального программирования придет со временем. Если говорить простым языком, то в функцию или метод (надеюсь знаете в чем отличие) можно передавать параметры — мы это делаем каждый день — передаем целые или строки или объекты. Но также в качестве параметров можно передавать и другие функции. Причем в данном случае (запрос удаленных данных) даже понятно зачем это делать. Т.е. мы предаем ту функцию, которую мы хотим запустить, после получения данных из запроса. А функция эта будет оперировать данными, которые получили.

Надеюсь не запутал, а все-таки объяснил, что именно тут присходит. В любом случае жду комментарии с пожеланиями и вопросами.

Объект response, с которым мы работаем содержит ответ сервера на наш запрос. Для начала мы проверили, что запрос успешен и если нет, ты выдали описание ошибки в консоль и вышли из метода. Если запрос прошло успешно то просто вывели его в консоль.

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

Если в консоле подобная информация, то все работает правильно.



Добавление дополнительных элементов

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

Таблица

Из библиотеки объектов перетащите таблицу на контроллер, разместите ее и задайте размеры и ограничения. Также создайте outlet — свойство для работы с этой таблицей.

 

Не забудьте создать связи между таблицей и контроллером, чтобы работали методы UITableViewDelegate и UITableViewDataSource. Для этого выполните ctrl-перетаскивание от таблицы к значку контроллера и отметьте нужны пункты:

Класс ячейки таблицы

Из библиотеки объектов перетащите ячеку в таблицу. Настройте высоту ячейки (я сделал 64), и разместите на этой ячейке нужные элементы — четыре надписи. Если есть желание, — измените цвета. Задайте размеры и ограничения.  ОБЯЗАТЕЛЬНО задайте ReuseIdentifier — я указал «Cell«

В новый файл или в файл с контроллером (ViewController.swift) добавьте определения класса ячейки таблицы:

После этого создайте outlet-свойства для всех надписей в ячейке. У меня проект выглядит так:

Класс ячейки у меня выглядит так:

Класс структуры

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

Методы протоколов UITableViewDataSource и UITableViewDelegate и свйоство.

В класс контроллера добавьте свойство для хранения элементов

Методы протоколов я добавил в расширении:

Думаю, подробные объяснения не требуются — первый метод устанавливает количество строк по поличеосту элементов в массиве с объектами. Второй метод — метод который возвращает ячейку таблицы для нужной строки и третий метод — это метод заполнения ячейки нужными данными.

 

Обработка данных

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

Перейдите к методу, который срабатывает по нажатию на кнопку. Найдите ветку, в которой мы выводим в консоль данные, полученные при запросе и замените строку print() на следующий код:

Давайте разбирать. Мы взяли данные из response.result.value и пробуем перевести их в массив словарей, с ключом типа String и значением типа AnyObject. Формат такой именно потому, что данные приходят именно так, — приходит множество словарей, каждый из которых описывает один элемент. Если по какой-либо причине данные пришли в другом формате, то в консоль выйдет сообщение с ошибкой и выполнение метода прекратится.

Затем цикл перебирает элементы по одному, на основании данных из них создает объекты Item и помещает эти объекты в массив (свойство для хранения элементов для таблицы).

Запустите проект, нажмите на кнопку…  и вы увидите, что ничего не произойдет:

 

Догадались почему?

Давайте вспомним все, что было написано выше немного по-рассуждаем… Таблица создается во время запуска приложения. В этот момент данных у нас нет. Данные появляются только после нажатия на кнопку. И то, нужно некоторое время на их получение, обработку и добавление в массив items.  Нужно запустить метод таблицы reloadData() для отображения полученных данных. Но этот метод нужно запустить уже после заполнения массива.  Не забудьте, что запустить его нужно в основном потоке, т.к. мы помним, что запросы и обработка данных выполняется в фоновом потоке, а все методы работы с интерфейсом должны выполняться только в основном. У нас есть функция, которая выполняется после выполнения запроса. Давайте туда и поместим вызов метода обновления данных для таблицы.

Запускайте проект, нажимаетй на кнопку и наблюдайте результат.

Код всего файла ViewController.swift

Ссылка проекта на GitHub




Метки: ,
6 комментариев на “Alamofire на примере
  1. Иззз:

    > Добавьте в проект пустой файл и назовите его Podfile
    Куда именно ? Методом проб и ошибок выявилось, что podfile должен лежать на одном уровне с .xcodeproj

    > Откройте Terminal и перейдите в каталог с проектом
    Опять же на какой уровень ? У меня начало работать — см. выше

    > После завершения скачивания библиотеки Alamofire
    Здесь нужно предупредить читателя, что процедура может занять до 1 часа, всё это время cocoapods безапеляционно выполняет следующие действия: скачивание, распаковка, проверка

    > появится файл с названием вашего проекта, но расширение у него будет xworkspace
    Хотелось бы получить содержимое этого файла с описанием, так как не представляется возможным проверить корректность этого файла (а, значит, установки библиотеки) без какого-либо понимания «что должно быть-то ?»

    И да, у меня все папки есть, а в проект подключить Alamofire не могу — не видит библиотеку

    • admin:

      Для детального понимания системы управления зависимостями почитайте про Cocoapods. Многие вопросы отвалятся сами собой.

  2. Иззз:

    И ААААбязатЕльнА нужно сказать, что после установки библиотеки требуется УДАЛИТЬ Podfile из проекта
    Иначе библиотеку XCode не увидит

    • admin:

      Файл можно удалить, но дело в том, что Podfile является частью системы управления зависимостями. Удалять его точно не обязательно, особенно если Вы планируете обновлять сторонние модули и библиотеки, которые подключили к проекту. Например, если разработчик выпустит новую версию библиотеки (а Alamofire обновляется с завидной регулярностью), то без Podfile Вам придется обновлять исходники вручную.

  3. Иззз:

    И это не всё ! После нужно выполнить Product -> Clean, затем Product -> Build
    вот тогда библиотека будет видна

    • admin:

      Данный рецепт помогает во многих случаях, при которых Xcode глючит, не только тогда, когда не видит Alamofire

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.