Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Swift Hierarchical Selector Component based on UIPickerView & UICollectionView

DZone's Guide to

Swift Hierarchical Selector Component based on UIPickerView & UICollectionView

Learn how to create richer selector views in your Swift apps

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.


After all the excitement of globular metaballspressure sensitive drawing and weighing plums using 3D Touch, it’s back to a slightly more pedestrian subject: a “hierarchical selector” composite component using a UIPickerView to navigate categories and a UICollectionView to select items from those categories.

This component will be part of version 3 of Nodality, my node based image processing application. In Nodality, Core Image filter categories (such as blur) will be the categories and the filters themselves (such as Gaussian Blur) will be the items.

In the demo application, I’m using countries as categories and a handful of their cities as the items. When the taps on a city item, a map centers onto that selected city. I’ve also added a ‘back’ button - just to prove that the new component can be set programatically. 

If the selected item belongs to a category that's not currently displayed, I append a bullet to the category name.

The component has the natty title of FMHierarchicalSelector and is available at my GitHub repository here.

Implementing FMHierarchicalSelector

To use FMHierarchicalSelector in your own project, you’ll need a delegate that implements FMHierarchicalSelectorDelegate. This protocol contains three methods:

Categories

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

Returns an array of categories (FMHierarchicalSelectorCategory). Categories are simply strings, so my implementation for the demo simply looks like:

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

Items

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

Returns a flat array of all of the items. Your item type must implement  FMHierarchicalSelectorItem which includes getters and setters for the items name and category. Obviously, you can add whatever additional data you need, so for my project I’ve created an Item struct that also has a coordinate property of type CLLocationCoordinate2D. 

My itemsForHierarchicalSelector() looks a little like this:

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)),

Responding to Change

func itemSelected(hierarchicalSelector: FMHierarchicalSelector, item: FMHierarchicalSelectorItem)

The final function in FMHierarchicalSelectorDelegate is invoked on the delegate when the user selects a new item (city in the case of the demo).

The item argument is of type FMHierarchicalSelectorItem, so in my implementation, I attempt to cast it as an Item and if successful, I can extract the geographic coordinates of the selected city and update my map accordingly:

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)
}

In Conclusion

Although the visual design of FMHierarchicalSelector is very much geared to the next version of Nodality, its designed to work with any kind of data and is, therefore, a pretty versatile component to enable users to navigate through large datasets. FMHierarchicalSelector is available at

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:
swift ,ios

Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}