Давайте создадим ленту Hacker News API с бесконечной прокруткой

Введение Combine, среды реактивного программирования Apple, сделало URLSession и несколько других типов Foundation намного более мощными.

URLSession буквально на стероидах, а его издатель (dataTaskPublisher) позволяет нам делать много вещей. В частности, операторы Combine позволяют нам легко декодировать, повторять попытки, обрабатывать ошибки и связывать несколько запросов, среди прочего.

Наша цель

Цель этой статьи - создать список бесконечной прокрутки SwiftUI. Для этого мы будем использовать Combine и URLSession в Hacker News API в нашем приложении для iOS.

Если фреймворк Combine для вас новичок, я бы порекомендовал вам просмотреть Глубокое погружение в фреймворк Combine в Swift, прежде чем продолжить.

К концу этой части вы сможете добиться следующего результата:

Начиная

Чтобы настроить список SwiftUI, отображающий данные из веб-API, нам нужно настроить класс ObservableObject, как показано ниже:

Оператор карты преобразует результат API в нового издателя, который возвращает data из ответа API.

Важно установить receive(on:) для основного потока для обновления списка и store подписку в отменяемом экземпляре, чтобы поддерживать его в действии.

Мы будем использовать эти данные на следующем этапе для декодирования JSON с использованием протокола Codable, как показано ниже:

Структура HNItem должна соответствовать протоколу Identifiable для списка SwiftUI, чтобы отличать каждую строку от других.

Результаты API устанавливаются в свойстве hnItems класса HackerNewsFeed. Поскольку у него есть оболочка свойства Published, изменения отражаются в списке SwiftUI, как показано ниже:

Впоследствии в нашем симуляторе мы получаем следующий результат:

Таким образом, мы добавили URLSession результатов в список SwiftUI. Но список еще нельзя прокручивать бесконечно. Давай настроим это.

SwiftUI List Endless Scroll

В настоящее время SwiftUI не предоставляет встроенной поддержки для прослушивателя прокрутки. К счастью, для этого есть обходной путь.

Чтобы настроить бесконечную прокрутку в списке SwiftUI, нам нужно обработать следующие сценарии в нашем коде:

  • Используя метод onAppear в строках списка, мы можем определить, когда пользователь достиг последнего элемента, и соответственно вызвать запрос API для следующей страницы.
  • Чтобы предотвратить дублирование запросов API и обеспечить синхронизацию сетевых запросов, мы будем использовать перечисление для отслеживания состояния.

Кроме того, мы можем настроить другое перечисление для обработки ошибок.

Обновленный код для класса HackerNewsFeed, расширяющего ObservableObject, приведен ниже:

Мы изменили несколько вещей в функции fetchStories в приведенном выше коде:

  • Пока запрос не вернет результат, перечисление pageStatus настроено на загрузку.
  • tryMap используется вместо оператора map для обработки сетевых ошибок.
  • tryFilter используется для обработки пользовательских ошибок. В нашем случае свойство exhaustiveNbHits возвращается как false при достижении лимита запросов API. Итак, мы выдаем соответствующую ошибку, которая вызывает сбой в sink.
  • endOfList - это новое опубликованное свойство, используемое для вызова диалогового окна с предупреждением об определенных ошибках.

Функция shouldLoadMore решает, когда запускать следующий запрос API во время пользовательской прокрутки. Он вызывается во время onAppear в строках списка, как показано ниже:

В результате мы получим результат, как показано ранее.

API-интерфейс Hacker News, который мы использовали в приложении, имеет ограничение в 1000 результатов. Достигнув конца прокрутки, мы получим диалоговое окно с предупреждением, как показано ниже:

Заключение

Мы смогли создать приложение Hacker News Stories с бесконечной прокруткой ленты новостей с помощью SwiftUI и Combine.

В дальнейшем вы можете использовать оператор replaceError или catch для обработки проблем синтаксического анализа в JSON и настройки издателя восстановления.

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

Код вышеуказанного iOS-приложения SwiftUI доступен в репозитории Github.

На этом все - спасибо за чтение.