Location

Kinvey allows you to express the location of entities, including users, as longitude and latitude points on the coordinate system. Based on this, you can run proximity queries to find the closest restaurants, shops, or friends to a given location.

Location queries are only possible when the data store is in Network mode. Location queries in Cache or Sync mode return an error.

Kinvey supports location information through special location queries.

Storing Locations

For an entity to have an associated location, it needs a GeoPoint object parameter mapped.

For example, the code below adds a geolocation property of type GeoPoint to a class named Event. The corresponding entity property on the backend must be named _geoloc.

import Kinvey

class Event: Entity {

    @objc dynamic var title: String?
    @objc dynamic var address: String?
    @objc dynamic var geolocation: GeoPoint?

    override class func collectionName() -> String {
        return "Event"
    }

    enum CodingKeys : String, CodingKey {

        case title
        case address
        case geolocation = "_geoloc"

    }

}

The GeoPoint class contains 2 properties: latitude and longitude. A GeoPoint can be instantiated from a CLLocationCoordinate2D -

import CoreLocation

// let coordinate: CLLocationCoordinate2D = <#your CLLocationCoordinate2D#>
let geolocation = GeoPoint(coordinate: coordinate)

GeoPoint objects are translated to a json array when they are sent to the server. This array contains 2 values: longitude and latitude (in this order).

For example:

let event = Event()
event.title = "Meetup"
event.geolocation = GeoPoint(latitude: 42.3133521, longitude: -71.1271963)

will be written to your Event collection as:

titlegeolocation
Meetup[-71.1271963, 42.3133521]

To capture the location of the device, use Core Location.

import CoreLocation

if CLLocationManager.locationServicesEnabled() {
    let manager = CLLocationManager()
    //... set up CLLocationManager and start updates
    if let coordinate = manager.location?.coordinate,
        let user = Kinvey.sharedClient.activeUser as? CustomUser
    {
        user.geolocation = GeoPoint(coordinate: coordinate)
    }
}

Queries

Query objects supports special geolocation queries using some MapKit objects

  • MKCircle: used for queries where you have a central point (center) and a distance limit (radius). Example: look for events near to me in a maximum distance of 20 kilometers.
import MapKit

//search for objects in a max distance of 7 kilometers
let query = Query(
        format: "\(Event.CodingKeys.geolocation.rawValue) = %@",
        MKCircle(center: coordinate, radius: 7000)
)
  • MKPolygon: used for queries where you have a shape of any form (polygon), triangle, square and so on. Example: look for events in downtown area.
import CoreLocation
import MapKit

let coordinates = [
    //bottom left corner
    CLLocationCoordinate2D(latitude: 42.31363114297847, longitude: -71.12454163288896),
    //bottom right corner
    CLLocationCoordinate2D(latitude: 42.31359338001615, longitude: -71.11596352589291),
    //top right corner
    CLLocationCoordinate2D(latitude: 42.32375212671243, longitude: -71.11492645316849),
    //top left corner
    CLLocationCoordinate2D(latitude: 42.32182013184487, longitude: -71.13022491168071)
]
let polygon = MKPolygon(coordinates: coordinates, count: coordinates.count)
// Search for objects inside the square defined by
// the points in the `coordinates` variable.
let query = Query(format: "\(Event.CodingKeys.geolocation.rawValue) = %@", polygon)

The default unit used by Core Location is meter (metric system). Remember to convert your values if they are in miles.