Swift Objective-C Ruby C++
Latest commit dea8b5f Feb 22, 2017 @1ec5 1ec5 v0.6.0

README.md

MapboxGeocoder

📱 iOS Build Status     🖥💻 macOS Build Status     📺 tvOS Build Status     ⌚️ watchOS Build Status

MapboxGeocoder.swift makes it easy to connect your iOS, macOS, tvOS, or watchOS application to the Mapbox Geocoding API. MapboxGeocoder.swift exposes the power of the Carmen geocoder through a simple API similar to Core Location’s CLGeocoder.

MapboxGeocoder.swift pairs well with MapboxDirections.swift, MapboxStatic.swift, and the Mapbox iOS SDK or macOS SDK.

Getting started

Specify the following dependency in your Carthage Cartfile:

github "Mapbox/MapboxGeocoder.swift" ~> 0.6

Or in your CocoaPods Podfile:

pod 'MapboxGeocoder.swift', :git => 'https://github.com/mapbox/MapboxGeocoder.swift.git', '~> 0.6'

Then import MapboxDirections or @import MapboxDirections;.

v0.5.2 is the last release of MapboxGeocoder.swift written in Swift 2.3. The swift2.3 branch corresponds to this release, plus any critical bug fixes that have been applied since. All subsequent releases will be based on the master branch, which is written in Swift 3. The Swift examples below are written in Swift 3; see the swift2.3 branch’s readme for Swift 2.3 examples.

This repository includes example applications written in both Swift and Objective-C showing use of the framework (as well as a comparison of writing apps in either language). More examples and detailed documentation are available in the Mapbox API Documentation.

Usage

You will need a Mapbox access token in order to use the API. If you’re already using the Mapbox iOS SDK or macOS SDK, MapboxGeocoder.swift automatically recognizes your access token, as long as you’ve placed it in the MGLMapboxAccessToken key of your application’s Info.plist file.

Basics

The main geocoder class is Geocoder in Swift or MBGeocoder in Objective-C. Create a geocoder object using your access token:

// main.swift
import MapboxGeocoder

let geocoder = Geocoder(accessToken: "<#your access token#>")
// main.m
@import MapboxGeocoder;

MBGeocoder *geocoder = [[MBGeocoder alloc] initWithAccessToken:@"<#your access token#>"];

Alternatively, you can place your access token in the MGLMapboxAccessToken key of your application’s Info.plist file, then use the shared geocoder object:

// main.swift
let geocoder = Geocoder.shared
// main.m
MBGeocoder *geocoder = [MBGeocoder sharedGeocoder];

With the geocoder in hand, construct a geocode options object and pass it into the Geocoder.geocode(_:completionHandler:) method.

Forward geocoding

Forward geocoding takes a human-readable query, such as a place name or address, and produces any number of geographic coordinates that correspond to that query. To perform forward geocoding, use ForwardGeocodeOptions in Swift or MBForwardGeocodeOptions in Objective-C.

// main.swift
#if !os(tvOS)
    import Contacts
#endif

let options = ForwardGeocodeOptions(query: "200 queen street")

// To refine the search, you can set various properties on the options object.
options.allowedISOCountryCodes = ["CA"]
options.focalLocation = CLLocation(latitude: 45.3, longitude: -66.1)
options.allowedScopes = [.address, .pointOfInterest]

let task = geocoder.geocode(options) { (placemarks, attribution, error) in
    guard let placemark = placemarks?.first else {
        return
    }

    print(placemark.name)
        // 200 Queen St
    print(placemark.qualifiedName)
        // 200 Queen St, Saint John, New Brunswick E2L 2X1, Canada

    let coordinate = placemark.location.coordinate
    print("\(coordinate.latitude), \(coordinate.longitude)")
        // 45.270093, -66.050985

    #if !os(tvOS)
        let formatter = CNPostalAddressFormatter()
        print(formatter.string(from: placemark.postalAddress!))
            // 200 Queen St
            // Saint John New Brunswick E2L 2X1
            // Canada
    #endif
}
// main.m
#if !TARGET_OS_TV
@import Contacts;
#endif

MBForwardGeocodeOptions *options = [[MBForwardGeocodeOptions alloc] initWithQuery:@"200 queen street"];

// To refine the search, you can set various properties on the options object.
options.allowedISOCountryCodes = @[@"CA"];
options.focalLocation = [[CLLocation alloc] initWithLatitude:45.3 longitude:-66.1];
options.allowedScopes = MBPlacemarkScopeAddress | MBPlacemarkScopePointOfInterest;

NSURLSessionDataTask *task = [geocoder geocodeWithOptions:options
                                        completionHandler:^(NSArray<MBGeocodedPlacemark *> * _Nullable placemarks,
                                                            NSString * _Nullable attribution,
                                                            NSError * _Nullable error) {
    MBPlacemark *placemark = placemarks[0];
    NSLog(@"%@", placemark.name);
        // 200 Queen St
    NSLog(@"%@", placemark.qualifiedName);
        // 200 Queen St, Saint John, New Brunswick E2L 2X1, Canada

    CLLocationCoordinate2D coordinate = placemark.location.coordinate;
    NSLog(@"%f, %f", coordinate.latitude, coordinate.longitude);
        // 45.270093, -66.050985

#if !TARGET_OS_TV
    CNPostalAddressFormatter *formatter = [[CNPostalAddressFormatter alloc] init];
    NSLog(@"%@", [formatter stringFromPostalAddress:placemark.postalAddress]);
        // 200 Queen St
        // Saint John New Brunswick E2L 2X1
        // Canada
#endif
}];

Reverse geocoding

Reverse geocoding takes a geographic coordinate and produces a hierarchy of places, often beginning with an address, that describes the coordinate’s location. To perform reverse geocoding, use ReverseGeocodeOptions in Swift or MBReverseGeocodeOptions in Objective-C.

// main.swift
let options = ReverseGeocodeOptions(coordinate: CLLocationCoordinate2D(latitude: 40.733, longitude: -73.989))
// Or perhaps: ReverseGeocodeOptions(location: locationManager.location)

let task = geocoder.geocode(options) { (placemarks, attribution, error) in
    guard let placemark = placemarks?.first else {
        return
    }

    print(placemark.imageName ?? "")
        // telephone
    print(placemark.genres?.joined(separator: ", ") ?? "")
        // computer, electronic
    print(placemark.administrativeRegion?.name ?? "")
        // New York
    print(placemark.administrativeRegion?.code ?? "")
        // US-NY
    print(placemark.place?.wikidataItemIdentifier ?? "")
        // Q60
}
// main.m
MBReverseGeocodeOptions *options = [[MBReverseGeocodeOptions alloc] initWithCoordinate: CLLocationCoordinate2DMake(40.733, -73.989)];
// Or perhaps: [[MBReverseGeocodeOptions alloc] initWithLocation:locationManager.location]

NSURLSessionDataTask *task = [geocoder geocodeWithOptions:options
                                        completionHandler:^(NSArray<MBGeocodedPlacemark *> * _Nullable placemarks,
                                                            NSString * _Nullable attribution,
                                                            NSError * _Nullable error) {
    MBPlacemark *placemark = placemarks[0];
    NSLog(@"%@", placemark.imageName);
        // telephone
    NSLog(@"%@", [placemark.genres componentsJoinedByString:@", "]);
        // computer, electronic
    NSLog(@"%@", placemark.administrativeRegion.name);
        // New York
    NSLog(@"%@", placemark.administrativeRegion.code);
        // US-NY
    NSLog(@"%@", placemark.place.wikidataItemIdentifier);
        // Q60
}];

Batch geocoding

With batch geocoding, you can perform up to 50 distinct forward or reverse geocoding requests simultaneously and store the results in a private database. Create a ForwardBatchGeocodingOptions or ReverseBatchGeocodingOptions object in Swift, or an MBForwardBatchGeocodingOptions or MBReverseBatchGeocodingOptions object in Objective-C, and pass it into the Geocoder.batchGeocode(_:completionHandler:) method.

// main.swift
let options = ForwardBatchGeocodeOptions(queries: ["skyline chili", "gold star chili"])
options.focalLocation = locationManager.location
options.allowedScopes = .pointOfInterest

let task = geocoder.batchGeocode(options) { (placemarksByQuery, attributionsByQuery, error) in
    guard let placemarksByQuery = placemarksByQuery else {
        return
    }

    let nearestSkyline = placemarksByQuery[0][0].location
    let distanceToSkyline = nearestSkyline.distance(from: locationManager.location)
    let nearestGoldStar = placemarksByQuery[1][0].location
    let distanceToGoldStar = nearestGoldStar.distance(from: locationManager.location)

    let distance = LengthFormatter().string(fromMeters: min(distanceToSkyline, distanceToGoldStar))
    print("Found a chili parlor \(distance) away.")
}

Batch geocoding is available to Mapbox enterprise accounts. See the Mapbox Geocoding website for more information.

Tests

To run the included unit tests, you need to use Carthage 0.19 or above to install the dependencies.

  1. carthage bootstrap
  2. open MapboxGeocoder.xcodeproj
  3. Switch to the “MapboxGeocoder iOS” scheme and go to Product ‣ Test.