All tutorials

Using the iOS Map Component

intermediate
The what3words Free API plan will no longer include convert-to-coordinate requests. To continue using this feature, please upgrade to one of our paid plans starting from £7.99/month. Learn more about our API plans here.

As a reminder, emergency services can make use of the what3words API for free, and we have a dedicated plan for NGOs and registered charities. If your organisation falls within these categories, please get in touch.

For any questions or assistance, feel free to reach out to support@what3words.com.

Introduction

The easiest way to add what3words to your technology is to use one of our components. We have several components available for JavaScript, iOS, and Android which require minimal development to integrate.

The what3words iOS Map Component provides a straightforward way to add what3words grid on top of your MKMapView or a full-featured map View Controller, displaying the what3words address and marker on the map for a selected  3 word address.
This tutorial steps through how our iOS Map Component can be added to a new project that requires creating a map from scratch or to an existing map:

  • If you are creating a new map from scratch using our Map component then we recommend using our Map Component: W3WMapViewController;
  • If you want to add what3words to an existing map then we recommend using our Map Helper: W3WMapHelper;
  • If you are looking for a quick and dirty way to get the what3words functionality into your app we recommend using our Map View: W3WMapView.

Follow the steps below to select your chosen way to integrate our what3words map component into your project.<

GitHub repo: https://github.com/what3words/w3w-swift-components.

Quickstart

The iOS Map Component requires just a few lines of code to be added to an iOS application to create a map with what3words functionality.

  • Replace YOUR-API-KEY with your what3words API key.
  • It is compatible with applications that are built using iOS 9.0 or higher.
  • If you are upgrading from any version 1.x.x, see this upgrade guide.

Here are listed some sample apps that can be used:

ios_map_component_final_result

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        self.set(language: "en")

        let textField = W3WAutoSuggestTextField(api)
        self.attach(textField: textField)

        textField.onSuggestionSelected = { suggestion in
            self.removeAllMarkers()
            self.addMarker(at: suggestion, camera: .zoom)
        }

        self.onSquareSelected = { square in 
            self.removeAllMarkers()
            self.addMarker(at: square, camera: .center)
            testField.set(display: square)
        }

        let button = W3WMapTypeButton()
        attach(view: button, position: .bottomRight)

        // if there is an error then add it as an alert
        onError = { error in self.showError(error: error) }
    }

    /// set here the showError() function
    func showError(error: Error) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: "Error", message: String(describing: error), preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Dismiss", style: .cancel, handler: nil))
            self.present(alert, animated: true)
        }
    }
}
Copied

Step by Step

1
2

Add the dependency

The iOS Map Component depends on the what3words swift wrapper, make sure you will add it as a Package Dependency. Follow these easy steps to add this swift package to your project:

  1. From Xcode’s File menu choose Swift Packages then Add Package Dependancy.
  2. The Choose Package Repository window appears. Add https://github.com/what3words/w3w-swift-components.git in the search box, and click on Next.
  3. If you are satisfied with the selected version branch choices, click Next again.
  4. You should then be shown as a “Package Product” W3WSwiftComponents. Choose Add Package.

Xcode should now automatically install w3w-swift-components, and w3w-swift-wrapper.

Go to your ViewController.swift file and add the following libraries:

import W3WSwiftApi
import W3WSwiftComponents
Copied
3

New app using W3WMapViewController

If you are starting a new project and you are creating a new app from scratch, we recommend using our W3WMapViewController which is a high-level component that has easy-to-use what3words functionality.

Add the following class W3WMapViewController to the ViewController of your project. You will just have a Map view, no what3words functionality has been added yet at this point.

import UIKit
import W3WSwiftApi
import W3WSwiftComponents

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}
Copied

You will need to add your what3words API key here to display the Map Component:

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
    }
}
Copied

To refer to the map add the following line of code to your viewDidLoad() function below the api variable:

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")

        // set the map view --> self = map  
        self.set(api)
    }
}
Copied

After adding this snippet run your application and you will display the Apple Maps with the what3words grid on top of it.

grid_on_map

Customise the Map Component

The Map Component can be customised using some what3words properties. Here is shown an example where you can add a simple market to your Map with a specified what3words address. It will place an annotation on the map, if the map is zoomed in, it will appear as a square, and if zoomed out it shows as a what3words annotation icon.

customise_map_component

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        // add Marker with a specified what3words address
        self.addMarker(at: "filled.count.soap")

    }
}
Copied

You can set a language to get all the 3wa in the desired language (default english) by adding this line of code within the viewDidLoad function:

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        // set language to get all the what3words
        self.set(language: "en")

        self.addMarker(at: "filled.count.soap")

    }
}
Copied

You can make the map marker change color or their position on the map or add a list of specified what3words addresses.

Note: the default colour of the marker is the brand’s red.

multiple_markers

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        self.set(language: "en")

        // an example on how to add a blue marker on a valid 3 word address and move the map view to the center with multiple markers on the map
        self.addMarker(at:["filled.count.soap", "index.home.raft"], camera: .center, color: .blue)

    }
}
Copied

You could also pass in a what3words suggestion to the addMarker property:

suggestions_marker

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        self.set(language: "en")

        // an example on how to add a what3words suggestions to the marker
        api.autosuggest(text: "filled.count.s") { suggestions, error in 
            self.addMarker(at: suggestions)
        }

    }
}
Copied

You could also restrict your what3words address suggestions to a desired country using W3WOptions() as shown here:

suggestions_marker_with_clipping

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        self.set(language: "en")

        // an example on how to add a what3words suggestions to the marker clipped to a desired country
        let options = W3WOptions().clipToCountry("GB")
        api.autosuggest(text: "filled.count.s", options: options) { suggestions, error in 
            self.addMarker(at: suggestions)
        }

    }
}
Copied

Access the map view

To access the Map View you can use an accessor variable called w3wMapView which is an MKMapView.

Listening for events

Now when you click on the map marker you can display the what3words address if you trigger the onSquareSelected event.

Note: Only one square can be selected at the same time, just like our core apps.

selected_square

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        self.set(language: "en")

        // an example when a point is touched on the map and highlights its 3x3m what3words square,
        self.onSquareSelected = { square in 
            // this clears previous what3words annotations and selected squares
            self.removeAllMarkers()
            self.addMarker(at: square, camera: .center)
        }

    }
}
Copied

Use AutoSuggest Component in the Search field

If you want to add the AutoSuggest Component to the search box on top of the Map Component, you need to update your viewDidLoad() function to both have the what3words components, the W3WAutoSuggestTextField (for the AutoSuggest Component) and W3WMapViewController (for the Map Component).

autosuggest_text_field

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        self.set(language: "en")

        // Add an AutoSuggest Component text field, and attach it to the view
        let textField = W3WAutoSuggestTextField(api)
        self.attach(textField: textField)

        // when an AutoSuggest suggestion is selected from the text field, show it on the map and clear previous selections
        textField.onSuggestionSelected = { suggestion in
            self.removeAllMarkers()
            self.addMarker(at: suggestion, camera: .zoom)
        }

        self.onSquareSelected = { square in 
            self.removeAllMarkers()
            self.addMarker(at: square, camera: .center)
            // this add the what3words address to the text field
            textField.set(display: square)
        }
    }
}
Copied

If you want to add the voice functionality to the AutoSuggest Text Field Component you need to make sure to add the following line of code right after you declare the textField variable

let textField = W3WAutoSuggestTextField(api)
// Add an AutoSuggest text field component with the voice option, and attach it to the view (voice functionality requires API key permissions, contact what3words to enable this - https://accounts.what3words.com/overview)
textField.set(voice: true)
attach(textField: textField)
Copied

Customise map type

If you are familiar with MKMapView you can set up different map types MKMapType, for example:

  • .standard if you want to display street map
    mapView.mapType = .standard
  • .satellite if you want to displays satellite imagery
    mapView.mapType = .satellite

Here is what your application should look like:

ios_map_component_final_result

4

Existing app using W3WMapHelper

If you already have an application with a map we recommend using our Map Helper, W3WMapHelper in your app. It provides convenience functions to add to your MKMapViewDelegate functions for what3words grid and pin annotations to be displayed on your map.

An iOS UIKit example project can be out here. This example shows where you would place the calls, and how to instantiate the W3WMapHelper.

Note: the W3WMapHelper is conforms to the W3WMapViewProtol. A function reference is described below in the Map Component Functions.

let api = What3WordsV3(apiKey: "YourApiKey")
let mapHelper = W3WMapHelper(api, map: yourMKMapView)
Copied
5

Existing app using W3WMapView

If you are keen on using our Map View, W3WMapView, as a quick and dirty way to quickly get what3words functionality into your app, simply replace your MKMapView with W3WMapView, and your app should behave the same as before except it will draw what3words grid lines and have some new functions available, like addMarker(at: "filled.count.soap").

The W3WMapView is derived from MKMapView but Apple does not recommend deriving new objects from MKMapView presumably, because its interface could change in the future.

A better approach to inserting our map component into your existing map would be to use our W3WMapHelper which is designed to fit nicely into your MKMapViewDelegate conforming class, presumably a UIViewController.

An iOS UIKit example project can be out here.

Note: the W3WMapHelper is conforms to the W3WMapViewProtol. A function reference is described below in the Map Component Functions.

let api = What3WordsV3(apiKey: "YourApiKey")
let mapview = W3WMapView(api)
Copied
6

Configuring for use with API server

If you run our Enterprise Suite API Server yourself, you may specify the URL to your own server by adding this line of code to the Map Component:

val api = What3WordsV3(apiKey: "YOUR_API_KEY_HERE", apiUrl: "https://api.yourserver.com")
Copied
7

Map Component Functions

Method NameDescriptionExample
addMarker(at: _, camera: W3WCenterAndZoom, color: UIColor?, style: W3WMarkerStyle)This parameter will place an annotation on the map, if the map is zoomed in, it will appear as a square, and if zoomed out it shows as a what3words annotation icon. addMarker(at:camera:color) takes one required parameter and two optional ones. The first is the location, this can be a what3words address as: - words: String, - suggestion: W3WSuggestion, - squares: W3WSquare, - coordinates: CLLocatioinCorrdinate2D, - or it can be an array of any of those. Note: if you pass in a String, or W3WSuggestion, a call to convertToCoordinates will be made automatically to get the coordinates, and this will count towards your account quota. The second and optional parameter is called camera and it indicates how to move the map view. The choices are: - .zoom - zooms the map into the location right around the square - .center - adjusts the map's center so that the location is in the center, but does not zoom in - .none - this leaves the mapView showing the same area it was showing before the call The third and optional parameter is color which takes a UIColor color for the annotation. The default colour is the what3words brand's red.map.addMarker(at:square, camera: .zoom) map.addMarker(at:"filled.count.soap", style: .pin) map.addMarker(at:["filled.count.soap", "index.home.raft"], camera: .center) map.addMarker(at:["filled.count.soap", "index.home.raft"], color: .blue, camera: .center)
getMapAnnotationView(annotation: MKAnnotation) -&gt; MKAnnotationView?If the annotation is a what3words one, this parameter gets a renderer, otherwise, it returns nil. If you are using W3WMapHelper then this is typically called in your MKMapViewDelegate's call: mapView(_, viewFor: MKAnnotation)getMapAnnotationView(annotation: annotation)
mapRenderer(overlay: MKOverlay) -&gt; MKOverlayRenderer?addMarkerAtWordsThis parameter gets a renderer for the what3words grid if it is given a W3WMapGridLines or W3WMapSquareLines overlay, otherwise, it returns nil. If you are using W3WMapHelper then this is typically called in your MKMapViewDelegate's call: mapView(_, rendererFor: MKOverlay)mapRenderer(overlay: overlay)
removeAllMarkers()This parameter will hide an annotation that was previously placed on the map. It takes one parameter and like addMarker(), it can be a what3words address as: - words: String, - suggestion: W3WSuggestion, - coordinates: CLLocatioinCorrdinate2D, - or it can be an array of any of those.map.removeAllMarkers()
removeMarker(at:)This method allow you to get all added markers from the map.map.removeMarker(at: square) map.removeMarker(at: "filled.count.soap") map.removeMarker(at: ["filled.count.soap", "index.home.raft"])
set(language: String)This parameter will set the default language for all the calls that the map makes to the API (or SDK if you use that instead).map.set(language: "fr") // set default language to French
set(zoomInPointsPerSquare: CGFloat)This parameter will set how near the addMarker(at: "filled.count.soap", camera: .zoom) calls will zoom. zoomInPointsPerSquare is the size of squares in points when .zoom is used in an addMarker() call. (points being 1x, 2x, 3x a pixel depending on which device you are using and if it has a "retina" display.set(zoomInPointsPerSquare: x.x)
updateMap()This parameter updates the map view with annotations and lines. If you are using W3WMapHelper then this is typically called in your MKMapViewDelegate's calls: mapViewDidChangeVisibleRegion() mapView(_, regionWillChangeAnimated), and mapView(_, regionDidChangeAnimated).updateMap()
8

Events

EventDescriptionExample
onMarkerSelectedThis parameter is called when the user taps a square that has a marker added to it.self.onMarkerSelected = { square in self.addMarker(at: square, camera: .center)}
onSquareSelectedThis parameter is called when the user taps a square on a map.self.onSquareSelected = { square in self.addMarker(at: square, camera: .center)}
onErrorThis parameter returns the error enum for any error that occurs.onError = { error in self.showError(error: error) }

Listening for events

Using an event listener, it is possible to fire other functionality in an app when something changes in the Map Component. For example, when you click on the map marker you can display the what3words address if you trigger the onSquareSelected event.

Note: Only one square can be selected at the same time, just like our core apps.

class ViewController: W3WMapViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let api = What3WordsV3(apiKey: "Enter your what3words API key")
        self.set(api)

        self.set(language: "en")

        // an example when a point is touched on the map and highlights its 3x3m what3words square,
        self.onSquareSelected = { square in 
            // this clears previous what3words annotations and selected squares
            self.removeAllMarkers()
            self.addMarker(at: square, camera: .center)
        }

    }
}
Copied
9

Troubleshooting

If you encounter errors or issues related to convert-to-coordinate requests while using the Free plan, please check the network panel for the following error message Error 402 payment required and its response, indicating the need to upgrade to a higher plan:

{
    "error": {
        "code": "QuotaExceeded",
        "message": "Quota Exceeded. Please upgrade your usage plan, or contact support@what3words.com"
    }
}
Copied

For more information, visit our API plans page. If you need further assistance, contact support@what3words.com.

Issue

How to make the textfield suggest actual addresses (not w3w)?

Solution

Currently, it’s not possible with the iOS AutoSuggest Component. There is, however, an example of this in w3w-swift-wrapper called AutosuggestPlusYourData. You can use this as a guide or even take some of the code from it for your use.

Mobile AppAdd a 3 word address input fieldDisplay a 3 word addressUse 3 word addresses with a mapUse 3 word addresses within an address searchSwift

Related tutorials