Статьи

Компонент Swift Hierarchical Selector, основанный на UIPickerView и UICollectionView

После всего волнения  шаровых мета-шариковрисования, чувствительного к давлению,  и  взвешивания слив с помощью 3D Touch , мы возвращаемся к чуть более пешеходному предмету: составному компоненту «иерархический селектор», использующему UIPickerView для навигации по категориям и UICollectionView для выбора элементов из этих категорий.

Этот компонент будет частью 3-й версии  Nodality , моего приложения для обработки изображений на основе моего узла. В Nodality категории фильтра Core Image (такие как  размытие ) будут категориями, а сами фильтры (такие как  Gaussian Blur ) будут элементами.

В демонстрационном приложении я использую страны в качестве категорий и несколько их городов в качестве элементов. При нажатии на элемент города карта центрируется на выбранном городе. Я также добавил кнопку «назад» — просто чтобы доказать, что новый компонент может быть установлен программно. 

Если выбранный элемент принадлежит категории, которая в данный момент не отображается, я добавляю маркер к названию категории.

Компонент имеет полезный заголовок FMHierarchicalSelector и доступен в  моем репозитории GitHub здесь .

Внедрение FMHierarchicalSelector

Чтобы использовать FMHierarchicalSelector в вашем собственном проекте, вам потребуется делегат, который реализует FMHierarchicalSelectorDelegate. Этот протокол содержит три метода:

категории

func categoriesForHierarchicalSelector(hierarchicalSelector: FMHierarchicalSelector) -> [FMHierarchicalSelectorCategory]

Возвращает массив категорий (FMHierarchicalSelectorCategory). Категории — это просто строки, поэтому моя реализация для демонстрации выглядит так:

let categories: [FMHierarchicalSelectorCategory] = [
    "Australia",
    "Canada",
    "Switzerland",
    "Italy",
    "Japan"].sort()

Предметы

func itemsForHierarchicalSelector(hierarchicalSelector: FMHierarchicalSelector) -> [FMHierarchicalSelectorItem]

Возвращает плоский массив всех элементов. Ваш тип элемента должен реализовывать FMHierarchicalSelectorItem, который включает в себя методы получения и установки для имени и категории элементов. Очевидно, что вы можете добавить любые дополнительные данные, которые вам нужны, поэтому для моего проекта я создал структуру Item, которая также имеет свойство координат типа CLLocationCoordinate2D. 

Мои itemsForHierarchicalSelector () выглядит примерно так:

let items: [FMHierarchicalSelectorItem] = [
    Item(category: "Australia", name: "Canberra", coordinate: CLLocationCoordinate2D(latitude: -35.3075, longitude: 149.1244)),
    Item(category: "Australia", name: "Sydney", coordinate: CLLocationCoordinate2D(latitude: -33.8650, longitude: 151.2094)),

Отвечая на изменения

func itemSelected(hierarchicalSelector: FMHierarchicalSelector, item: FMHierarchicalSelectorItem)

Последняя функция в FMHierarchicalSelectorDelegate вызывается для делегата, когда пользователь выбирает новый элемент (город в случае демонстрации).

Аргумент item имеет тип FMHierarchicalSelectorItem, поэтому в моей реализации я пытаюсь преобразовать его в «Предмет», и в случае успеха я могу извлечь географические координаты выбранного города и соответствующим образом обновить свою карту:

func itemSelected(hierarchicalSelector: FMHierarchicalSelector, item: FMHierarchicalSelectorItem)
{
    guard let item = item as? Item else
    {
        return
    }

    let span = MKCoordinateSpanMake(0.5, 0.5)
    let region = MKCoordinateRegionMake(item.coordinate, span)

    mapView.setRegion(region, animated: false)

    history.append(item)
}

В заключении

Хотя визуальный дизайн FMHierarchicalSelector в значительной степени ориентирован на следующую версию Nodality, он предназначен для работы с любыми типами данных и поэтому является довольно универсальным компонентом, позволяющим пользователям перемещаться по большим наборам данных. FMHierarchicalSelector доступен по адресу