Давайте создадим iOS-приложение для выбора страны

В этом коротком руководстве мы реализуем нашу пользовательскую панель поиска LazyVStack, которая содержит данные с разделами и индексом раздела, вдохновленные этим вопросом StackOverflow.

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

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

Наш готовый продукт будет выглядеть так:

Как мы видим, у нас есть список элементов с разделами. У каждого раздела есть индекс в правой части экрана, и когда мы нажимаем на значение индекса, наш список прокручивается до выбранного раздела. Также, когда мы вводим текст в строку поиска, фильтруется наш список элементов с разделами.

Итак, давайте создадим наш проект. Структура нашего проекта будет выглядеть так:

Во-первых, нам нужно добавить CountryCodes.json файл. Структура файла выглядит так:

Итак, давайте создадим наш CountryModel.swift, который будет содержать наши данные из файла JSON.

Далее мы реализуем CountryCodeViewModel.swift, который отвечает за выборку данных из файлов JSON и за создание разделов.

Как мы видим в предыдущем разделе кода, когда мы инициализируем нашу модель представления, мы инициализируем массив или страны из файла JSON.

Затем мы добавим CountryItemView.swift, что будет представлять наш кликабельный элемент списка.

Итак, последнее, что осталось реализовать, это CountryCodeView.swift. Он объединяет весь предыдущий код. Итак, давайте разобьем тело нашего представления на несколько частей.

Панель поиска создается по индивидуальному заказу, как показано ниже:

Следующий важный компонент — countriesListView:

Давайте остановимся прямо здесь и объясним самую важную часть приложения.

Прежде всего, мы добавили LazyVStack внутри ScrollView и ScrollViewReader с разделами. Каждый раздел, который является дочерним элементом внутри LazyVStack, закреплен с помощью pinnedViews:[.sectionHeaders].

Затем мы перебираем каждый раздел или букву в массиве разделов и добавляем раздел как CountrySectionHeaderView.

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

self.searchForSection($0)

Затем, пока мы перебираем разделы, мы фильтруем названия наших стран в нашей модели представления, беря первую букву каждой страны и сравнивая ее с буквой текущего раздела. Этот фильтр добавляет отфильтрованные страны в нужный раздел.

(countryModel) -> Bool in countryModel.name.prefix(1) == letter

В то же время мы используем другой фильтр для ввода нашей панели поиска, который фильтрует страны в нашей модели просмотра, вызывая функцию searchForCountry. Эта функция фильтрует страны в зависимости от строки, которую пользователь ввел в строке поиска.

self.searchForCountry(countryModel.name)

scrollProxy из ScrollViewReader позволяет нам прокручивать к началу каждого раздела нашего элемента индексного списка, по которому щелкнули.

scrollProxy.scrollTo(target, anchor: .topLeading)

Мы делаем это, прослушивая значение нашей переменной состояния scrollTarget. Эта переменная меняется в индексном списке lettersListView каждый раз, когда мы нажимаем кнопку с буквой из этого списка.

Button(action: {
   if countryCodeViewModel.countryCodes.first(where: {    $0.name.prefix(1) == letter }) != nil {
         scrollTarget = letter
   }
}

И последняя часть lettersListView.

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

Код доступен в приведенном ниже репозитории GitHub: