Building The Perfect iOS Map (I): Synchronising a Map and a List - Digital Leaves
post-template-default,single,single-post,postid-1335,single-format-standard,qode-social-login-1.0,qode-restaurant-1.0,ajax_fade,page_not_loaded,,select-theme-ver-4.1,wpb-js-composer js-comp-ver-5.2,vc_responsive

Building The Perfect iOS Map (I): Synchronising a Map and a List

A very common pattern in mobile applications is the kind of app where the data model involves a series of POI (points of interest) in a physical location. In this kind of scenario, the UI/UX involves having a map with those POI represented as pins alongside a list displaying the currently visible points. This map-list combination usually implies adjusting the list of POIs shown in the list dynamically as the user navigates through the map, by zooming in/out or swiping in any direction.

mini1476307456Many well-known apps like AirBnB and Idealista use this technique. In this tutorial, we are going to show how to build this kind of interface. We will be building an application that shows the museums of the USA in a main screen consisting of a map in the upper half and a list (UITableView) of the currently visible museums at the bottom, like the one depicted in the picture.

Our POIs will be a list of museums from the US, expressed in a comma-separated CSV. For the pins, we will use some custom pins found here. We will not discuss the user location in this tutorial, so we will be faking it to a fixed, hardcoded coordinate.

You can follow along the tutorial, or you can download the code right away from my Github repository.

Building the user interface

mini1476308739First we will build the user interface. We will set a MKMapView at the top, pinned to the top, left and right edges, and set a height equal to half the height of its superview. We will also add a UITableView at the bottom, pinned to the MKMapView at the top and to the bottom, left and right edges of the superview.

We will add one cell to the UITableView with the common title-subtitle style, so we can easily set the title to the name of the museum and the subtitle to the coordinate.

We will also set the MKMapView delegate and UITableView delegate and datasource to the ViewController, and will set the outlets in place for both controls.

Defining the POIs and data structures

We will create a PointOfInterest class as the main data structure of our model, with a name for the museum and the coordinate:

The “==” method defined for PointOfInterest will be useful later to look for annotations in the map with a given point of interest. We will get the data for the different POIs from a csv file with the following format:

The init?(csvLine: String) method will read a line of that file and generate a PointOfInterest. Our ViewController will have an array of points of interest, and we will read the values in viewWillAppear. Then we will center the map in a simulated fake user location and will display the annotation pins for that POIs.

The loadPointsOfInterest() method will just read the csv file line by line and create the different points of interest, adding them to the “poi” array:

centerMapInInitialCoordinates() just centers the map in a simulated user location, setting the visible map region to 100km. In a real application scenario, you will need to get the location of the user via CLLocationManager.

For showing the points of interest in a map, we will need to define a custom class that adheres to the MKAnnotation protocol, containing the point of interest. We will call our class POIAnnotation:

Then, we will just implement showPointsOfInterestInMap() by removing all current annotations in the map and adding an array of annotations with the current POIs:

For the list, we will just implement the numberOfRowsInSection and cellForRowAtIndexPath methods.

Up until this point, this is very basic stuff. Now we will make sure that selecting a POI in the UITableView brings us to the pin location at the map. In order to do that, we will create a method called selectPinPointInTheMap(annotation) and make sure to call it when selecting a row in tableView:didSelectRowAtIndexPath. Remember how we defined a “==” method for PointOfInterest? We will use it now to find the right annotation to select in the map, by getting the POI from the selected cell, and then iterate through all the iterations looking for an annotation whose PointOfInterest is equal to the one selected:

If we run the App now, it will show us all the list of POI, and if we click on any item of the list, the map will center on that POI and the MKAnnotationView will appear. Hooray!

Now let’s add the functionality to filter down the list to the points of interest currently shown in the map. We will do this by implementing the MKMapViewDelegate method mapView:regionDidChangeAnimated:. This method is invoked each time the visible region in the map changes, due to a zoom in/out pinch gesture or a swipe. This is exactly what we need. We will also need a variable to store the points that are currently visible in the map, called visiblePOI. We’ll make sure to update visiblePOI whenever a change in the poi origin array happens.

Then, we will create a new method called filterVisiblePOI and call it whenever the mapView:regionDidChangeAnimated: occurs.

Now, all we need to do is make sure that a change in poi will trigger an update in visiblePOI by means of the didSet event in the poi array, and we will modify all UITableViewDelegate/DataSource methods to make sure they get the information from visiblePOI instead of poi.

ezgif-com-optimizeWe will also add a call to filterVisiblePOI() in viewDidAppear, to make sure that we will start with the currently visible pins displayed in the list, not all of them.

And that’s it! The result is a nice interaction between the map and the list of POI. As always, you can download the full project in my github repository.




No Comments

Post a Comment

Before you continue...

Hi there! I created the Digital Tips List, the newsletter for Swift and iOS developers, to share my knowledge with you.

It features exclusive weekly tutorials on Swift and iOS development, Swift code snippets and the Digital Tip of the week.

Besides, If you join the list you'll receive the eBook: "Your First iOS App", that will teach you how to build your first iOS App in less than an hour with no prior Swift or iOS knowledge.

I hate spam, and I promise I'll keep your email address safe.