Skip to content

Geofence API

Client-side geofence monitoring is the process of tracking the position of the device in relation to the geofences defined in Backendless. Functionality  in Backendless client libraries loads information about geofences (or a specific geofence) and tracks device positional changes. When the device crosses, stays in, or exits a geofence boundary, the Backendless client executes a callback. Based on this, Backendless client-side monitoring supports the following options:

In-app callback interface

Client applications must use a special interface to receive local callbacks. The Backendless library invokes the interface methods when the current device's location enters, stays in or exits a geofence:

@protocol IGeofenceCallback <NSObject>

- (void)geoPointEnteredWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoFenceId:(NSString * _Nonnull)geoFenceId latitude:(double)latitude longitude:(double)longitude;
- (void)geoPointStayedWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoFenceId:(NSString * _Nonnull)geoFenceId latitude:(double)latitude longitude:(double)longitude;
- (void)geoPointExitedWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoFenceId:(NSString * _Nonnull)geoFenceId latitude:(double)latitude longitude:(double)longitude;

@end
@objc public protocol IGeofenceCallback {
    func geoPointEntered(geoFenceName: String, geoFenceId: String, latitude: Double, longitude: Double)
    func geoPointStayed(geoFenceName: String, geoFenceId: String, latitude: Double, longitude: Double)
    func geoPointExited(geoFenceName: String, geoFenceId: String, latitude: Double, longitude: Double)
}

Consider the following example of the in-app callback interface implementation. The example creates and saves a geopoint with dummy coordinates (0,0). As the device changes its location, the in-app callback is executed and the code saves the device's location on the server. See the example below.

// GeoFenceClientCallback.h 

@interface GeoFenceClientCallback : NSObject<IGeofenceCallback>

@property (strong, nonatomic) GeoPoint *me;

@end

// GeoFenceClientCallback.m

@implementation GeoFenceClientCallback

-(instancetype)init {
    if (self = [super init]) {
        self.me = [[GeoPoint alloc] initWithLatitude:0.0 longitude:0.0];
        [self savePoint];
    }
    return self;
}

-(void)savePoint {
    [Backendless.shared.geo saveGeoPointWithGeoPoint:self.me responseHandler:^(GeoPoint *savedPoint) {
        self.me = savedPoint;
        NSLog(@"Geopoint position has been updated");
    } errorHandler:^(Fault *fault) {
        NSLog(@"Error: %@", fault.message);
    }];
}

// IGeofenceCallback Methods

- (void)geoPointEnteredWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoFenceId:(NSString * _Nonnull)geoFenceId latitude:(double)latitude longitude:(double)longitude {
    self.me.latitude = latitude;
    self.me.longitude = longitude;
    [self savePoint];
}

- (void)geoPointStayedWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoFenceId:(NSString * _Nonnull)geoFenceId latitude:(double)latitude longitude:(double)longitude {
    self.me.latitude = latitude;
    self.me.longitude = longitude;
    [self savePoint];
}

- (void)geoPointExitedWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoFenceId:(NSString * _Nonnull)geoFenceId latitude:(double)latitude longitude:(double)longitude { 
    self.me.latitude = latitude;
    self.me.longitude = longitude;
    [self savePoint];
}

@end
class GeoFenceClientCallback: NSObject, IGeofenceCallback {

    var me: GeoPoint!

    required override init() {
        super.init()
        self.me = GeoPoint(latitude: 0.0, longitude: 0.0)
        self.savePoint()
    }

    func savePoint() {
        Backendless.shared.geo.saveGeoPoint(geoPoint: me, responseHandler: { savedPoint in
            self.me = savedPoint
            print("Geopoint position has been updated")
        }, errorHandler: { fault in
            print("Error: \(fault.message ?? "")")
        })
    }

    // IGeofenceCallback Methods

    func geoPointEntered(geoFenceName: String, geoFenceId: String, latitude: Double, longitude: Double) {
        me.latitude = latitude
        me.longitude = longitude
        savePoint()
    }

    func geoPointStayed(geoFenceName: String, geoFenceId: String, latitude: Double, longitude: Double) {
        me.latitude = latitude
        me.longitude = longitude
        self.savePoint()
    }

    func geoPointExited(geoFenceName: String, geoFenceId: String, latitude: Double, longitude: Double) {
        me.latitude = latitude
        me.longitude = longitude
        self.savePoint()
    }
}
  • Remote callback for the on enter, on stay and on exit event. The Backendless client automatically notifies the server when a geofence event occurs. If there is an action associated with the event, Backendless executes on the server-side.

The API applies the options above either to a specific or all geofences. It is important to note that a Backendless client can monitor only the geofences which are not activated for the server-side monitoring. In other words, a geofence with the "Is Active" toggle in the Backendless console set to ON cannot be tracked on the client-side.

iOS App Configuration

An iOS application can execute location updates in the background. The location updates are available when the app is killed, terminated or suspended. To activate this capability the following project options must be set:

  1. the "Background Modes" of the target's Capabilities is switched on, and "Location updates" and "Background fetch" are enabled:
    geoFence

  2. The NSLocationWhenInUseUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription keys are added to the .plist file.

Geofence APIs

The Geolocation service provides the following APIs:

Client-side location monitoring:

Executing a geofence action:

Retrieve geopoints from a geofence

Start location monitoring for a specific geofence with an in-app callback

Starts client-side monitoring of the device's location for the geofence. Uses the callback to notify when the device enters, stays in, or exits the geofence boundary.

- (void)startGeoFenceMonitoringWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoFenceCallback:(id<IGeofenceCallback> _Nonnull)IGeofenceCallback responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
func startGeoFenceMonitoring(geoFenceName: String, geoFenceCallback: IGeofenceCallback, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoFenceName name of a geofence, which monitors the device's location.
geoFenceCallback a callback object that the Backendless library notifies when the device crosses, stays in, or exits the geofence boundary.

Example

id<IGeofenceCallback> geoFenceCallback = [GeoFenceClientCallback new];
[Backendless.shared.geo startGeoFenceMonitoringWithGeoFenceName:@"Shopping Mall" geoFenceCallback:geoFenceCallback responseHandler:^{
    NSLog(@"Geofence monitoring has been started");
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
let geoFenceCallback = GeoFenceClientCallback()
Backendless.shared.geo.startGeoFenceMonitoring(geoFenceName: "Shopping Mall", geoFenceCallback: geoFenceCallback, responseHandler: {
    print("Geofence monitoring has been started")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Start location monitoring for all geofences with an in-app callback

Starts client-side monitoring of the device's location for all geofences. Uses the callback to notify when the device enters, stays in or exits a geofence boundary.

- (void)startGeoFenceMonitoringWithGeoFenceCallback:(id<IGeofenceCallback> _Nonnull)geoFenceCallback responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
func startGeoFenceMonitoring(geoFenceCallback: IGeofenceCallback, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoFenceCallback a callback object that the Backendless library notifies when the device crosses, stays in, or exits the geofence boundary.

Example

id<IGeofenceCallback> geoFenceCallback = [GeoFenceClientCallback new];
[Backendless.shared.geo startGeoFenceMonitoringWithGeoFenceCallback:geoFenceCallback responseHandler:^{
    NSLog(@"Geofence monitoring has been started");
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
let geoFenceCallback = GeoFenceClientCallback()
Backendless.shared.geo.startGeoFenceMonitoring(geoFenceCallback: geoFenceCallback, responseHandler: {
    print("Geofence monitoring has been started")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Start location monitoring for a specific geofence with a remote callback

Starts client-side monitoring of the device's location for a specific geofence. This function notifies the server when the device enters, stays in, or exits the geofence boundary.

- (void)startGeoFenceMonitoringWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoPoint:(GeoPoint * _Nonnull)geoPoint responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
func startGeoFenceMonitoring(geoFenceName: String, geoPoint: GeoPoint, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoFenceName name of a geofence, which monitors the device's location.
geoPoint the geopoint object to pass to the server. The geopoint represents the current device location. It may be a geopoint stored in the Geolocation storage (with objectId assigned to it) or a new geopoint object. The Backendless client assigns the current location coordinates to the geoPoint object before sending it to the server.

Example

// Create a geopoint.
// The coordinates are irrelevant because Backendless client will update them when the current location of the device where this program runs changes.
// The geopoint with the updated coordinates will be delivered to the server when the the current location triggers a geofence event.

GeoPoint *myLocation = [[GeoPoint alloc] initWithLatitude:0.0 longitude:0.0];
[Backendless.shared.geo startGeoFenceMonitoringWithGeoFenceName:@"Radio City Hall" geoPoint:myLocation responseHandler:^{
    NSLog(@"Geofence monitoring has been started");
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
// Create a geopoint.
// The coordinates are irrelevant because Backendless client will update them when the current location of the device where this program runs changes.
// The geopoint with the updated coordinates will be delivered to the server when the the current location triggers a geofence event.

let myLocation = GeoPoint(latitude: 0.0, longitude: 0.0)
Backendless.shared.geo.startGeoFenceMonitoring(geoFenceName: "Radio City Hall", geoPoint: myLocation, responseHandler: {
    print("Geofence monitoring has been started")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Start location monitoring for all geofences with a remote callback

Starts client-side monitoring of the device's location for all geofences. This function notifies the server when the device enters, stays in or exits a geofence boundary.

- (void) startGeoFenceMonitoringWithGeoPoint:(GeoPoint * _Nonnull)geoPoint responseHandler:^(void)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
func startGeoFenceMonitoring(geoPoint: GeoPoint, responseHandler: (() -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoPoint the geopoint object to pass to the server. The geopoint represents the current device location. It may be a geopoint stored in the Geolocation storage (with objectId assigned to it) or a new geopoint object. The Backendless client assigns current location coordinates to the geoPoint object before sending it to the server.

Example

// Create a geopoint.
// The coordinates are irrelevant because Backendless client will update them when the current location of the device where this program runs changes.
// The geopoint with the updated coordinates will be delivered to the server when the the current location triggers a geofence event.

GeoPoint *myLocation = [[GeoPoint alloc] initWithLatitude:0.0 longitude:0.0];

[Backendless.shared.geo startGeoFenceMonitoringWithGeoPoint:myLocation responseHandler:^{
    NSLog(@"Geofence monitoring has been started");
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
// Create a geopoint.
// The coordinates are irrelevant because Backendless client will update them when the current location of the device where this program runs changes.
// The geopoint with the updated coordinates will be delivered to the server when the the current location triggers a geofence event.

let myLocation = GeoPoint(latitude: 0.0, longitude: 0.0)
Backendless.shared.geo.startGeoFenceMonitoring(geoPoint: myLocation, responseHandler: {
    print("Geofence monitoring has been started")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Stop location monitoring for a specific geofence

Stops client-side monitoring of the device's location for the geofence.

- (void)stopGeoFenceMonitoringWithGeoFenceName:(NSString * _Nonnull)geoFenceName;
func stopGeoFenceMonitoring(geoFenceName: String)

where:

Argument                Description
geoFenceName name of the geofence for which device location monitoring will stop.

Example

[Backendless.shared.geo stopGeoFenceMonitoringWithGeoFenceName:@"Home"];
Backendless.shared.geo.stopGeoFenceMonitoring(geoFenceName: "Home")

Stop location monitoring for all geofences

Stops client-side monitoring of device locations for all geofences.

- (void)stopGeoFenceMonitoring;
func stopGeoFenceMonitoring()

Example

[Backendless.shared.geo stopGeoFenceMonitoring];
Backendless.shared.geo.stopGeoFenceMonitoring()

Run the OnEnter Action

Requests the server to run the configured OnEnter action for a geofence either for all geopoints located within the geofence or for the specified geopoint.

- (void)runOnEnterActionWithGeoFenceName:(NSString * _Nonnull)geoFenceName responseHandler:^(NSNumber * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;

- (void)runOnEnterActionWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoPoint:(GeoPoint * _Nonnull)geoPoint responseHandler:^(NSNumber * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
func runOnEnterAction(geoFenceName: String, responseHandler: ((NSNumber) -> Void)!, errorHandler: ((Fault) -> Void)!)

func runOnEnterAction(geoFenceName: String, geoPoint: GeoPoint, responseHandler: ((NSNumber) -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoFenceName name of the geofence on which the OnEnter action will run.
geoPoint a geopoint which will be used as the context for the action execution. Any substitutions which the action may be configured with will be resolved against the geopoint.

Example

[Backendless.shared.geo runOnEnterActionWithGeoFenceName:@"Home" responseHandler:^(NSNumber *geoPointsOnEnter) {
    NSLog(@"OnEnter action has been executed");
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];
Backendless.shared.geo.runOnEnterAction(geoFenceName: "Home", responseHandler: { geoPointsOnEnter in
    print("OnEnter action has been executed")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Run the OnStay Action

Requests the server to run the configured OnStay action for a geofence either for all geopoints located within the geofence or for the specified geopoint.

-(void)runOnStayAction:(NSString *)geoFenceName response:(void(^)(NSNumber *))responseBlock error:(void(^)(Fault *))errorBlock; 
// Objective-C
- (void)runOnStayActionWithGeoFenceName:(NSString * _Nonnull)feoFenceName responseHandler:^(NSNumber * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;
- (void)runOnStayActionWithGeoFenceName:(NSString * _Nonnull)GeoFenceName geoPoint:(GeoPoint * _Nonnull)geoPoint responseHandler:^(NSNumber * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;

// Swift
func runOnStayAction(geoFenceName: String, responseHandler: ((NSNumber) -> Void)!, errorHandler: ((Fault) -> Void)!)
runOnStayAction(geoFenceName: String, geoPoint: GeoPoint, responseHandler: ((NSNumber) -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoFenceName name of the geofence on which the OnEnter action will run.
geoPoint a geopoint which will be used as the context for the action execution. Any substitutions which the action may be configured with will be resolved against the geopoint.

Example

// Objective-C
[Backendless.shared.geo runOnStayActionWithGeoFenceName:@"Home" responseHandler:^(NSNumber *geoPointsOnStay) {
    NSLog(@"OnStay action has been executed");
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];

// Swift
Backendless.shared.geo.runOnStayAction(geoFenceName: "Home", responseHandler: { geoPointsOnStay in
    print("OnStay action has been executed")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Run the OnExit Action

Requests the server to run the configured OnExit action for a geofence either for all geopoints located within the geofence or for the specified geopoint.

-(void)runOnExitAction:(NSString *)geoFenceName response:(void(^)(NSNumber *))responseBlock error:(void(^)(Fault *))errorBlock; 
// Objective-C
- (void)Backendless.shared.geo runOnExitActionWithGeoFenceName:(NSString * _Nonnull)geoFenceName responseHandler:^(NSNumber * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;    
- (void)Backendless.shared.geo runOnExitActionWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoPoint:(GeoPoint * _Nonnull)geoPoint responseHandler:^(NSNumber * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;

// Swift
func runOnExitAction(geoFenceName: String, responseHandler: ((NSNumber) -> Void)!, errorHandler: ((Fault) -> Void)!)
func runOnExitAction(geoFenceName: String, geoPoint: GeoPoint, responseHandler: ((NSNumber) -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoFenceName name of the geofence on which the OnEnter action will run.
geoPoint a geopoint which will be used as the context for the action execution. Any substitutions which the action may be configured with will be resolved against the geopoint.

Example

[Backendless.shared.geo runOnExitActionWithGeoFenceName:@"Home" responseHandler:^(NSNumber *geoPointsOnExit) {
    NSLog(@"OnExit action has been executed");
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];

// Swift
Backendless.shared.geo.runOnExitAction(geoFenceName: "Home", responseHandler: { geoPointsOnExit in
    print("OnExit action has been executed")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

Retrieve Geopoints from a Geofence

Retrieves a collection of geopoints currently located within a geofence.

Methods with a block-based callback:

-(void)getFencePoints:(NSString *)geoFenceName response:(void(^)(BackendlessCollection *))responseBlock error:(void(^)(Fault *))errorBlock; 
// Objective-C
- (void)Backendless.shared.geo getFencePointsWithGeoFenceName:(NSString * _Nonnull)geoFenceName responseHandler:^(NSArray<GeoPoint *> * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;    
- (void)Backendless.shared.geo getFencePointsWithGeoFenceName:(NSString * _Nonnull)geoFenceName geoQuery:(BackendlessGeoQuery * _Nonnull)geoQuery responseHandler:^(NSArray<GeoPoint *> * _Nonnull)responseHandler errorHandler:^(Fault * _Nonnull)errorHandler;

// Swift
func getFencePoints(geoFenceName: String, responseHandler: (([GeoPoint]) -> Void)!, errorHandler: ((Fault) -> Void)!)
func getFencePoints(geoFenceName: String, geoQuery: BackendlessGeoQuery, responseHandler: (([GeoPoint]) -> Void)!, errorHandler: ((Fault) -> Void)!)

where:

Argument                Description
geoFenceName name of a geofence to retrieve the geopoints from.
geoQuery a BackendlessGeoQuery object controlling various aspects of geopoint retrieval such as paging, inclusion of metadata and/or SQL search query.

Example

The example loads geopoints from a geofence called "Manhattan". The returned geopoints will have metadata properties and will match the SQL query:

// Objective-C
BackendlessGeoQuery *geoQuery = [BackendlessGeoQuery new];
geoQuery.includemetadata = YES;
geoQuery.whereClause = @"businessType='restaurant' and rating > 3";

[Backendless.shared.geo getFencePointsWithGeoFenceName:@"Manhattan" geoQuery:geoQuery responseHandler:^(NSArray *geoPoints) {
    NSLog(@"Retrieved points: %@", geoPoints);
} errorHandler:^(Fault *fault) {
    NSLog(@"Error: %@", fault.message);
}];

// Swift
let geoQuery = BackendlessGeoQuery()
geoQuery.includemetadata = true
geoQuery.whereClause = "businessType='restaurant' and rating > 3"

Backendless.shared.geo.getFencePoints(geoFenceName: "Manhattan", geoQuery: geoQuery, responseHandler: { geoPoints in
    print("Retrieved points: \(geoPoints)")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})