Skip to content

PersistenceConfig

public classPersistenceConfig

Persistence and storage configuration for the background geolocation SDK.

PersistenceConfig controls how the SDK stores, orders, templates, and purges records in its on-device SQLite database — the durable buffer between data producers (locations, geofences) and consumers (your app and the HTTP service).

Contents

Overview

The SDK maintains an internal SQLite database as a rolling queue. Each recorded LocationEvent and geofence event is written immediately, then consumed and deleted by downstream services. The SDK prefers an empty database — records exist only while awaiting upload or retrieval.

Category Properties Notes
Retention maxDaysToPersist, maxRecordsToPersist TTL and count-based purge limits.
Ordering locationsOrderDirection Controls upload and retrieval order.
Templates locationTemplate, geofenceTemplate Custom JSON structure for uploads.
Extras extras Static key/value pairs merged into every record.
Persist mode persistMode Which event types are written to SQLite.
Diagnostics disableProviderChangeRecord Suppress provider-change records.
let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.maxDaysToPersist = 3
    config.persistence.maxRecordsToPersist = 1000
    config.persistence.extras = [
        "user_id": 123,
        "appVersion": "1.2.3"
    ]
    config.persistence.persistMode = .all
}

Storage lifecycle

Records are written to SQLite immediately upon recording and deleted when any of the following occur:

  • Your server returns a 20x response for the HTTP upload (see HttpConfig)
  • You call BGGeo.destroyLocations
  • maxDaysToPersist elapses (rolling TTL purge)
  • maxRecordsToPersist would be exceeded (oldest records are dropped)

Inspect the pending queue with BGGeo.getCount or BGGeo.getLocations.


Ordering

locationsOrderDirection controls the order in which records are selected for upload or returned by BGGeo.getLocations:

  • "ASC" — oldest first (default)
  • "DESC" — newest first

Templates

By default the SDK serializes locations and geofence events using its standard JSON schema. Use locationTemplate and geofenceTemplate to substitute a custom ERB template that reshapes the JSON to match your backend.

Use extras to merge static key/value metadata into every record at write time, without a custom template.


Persist mode

persistMode controls which event types are written to SQLite. All events are still delivered to their live callbacks (BGGeo.onLocation, BGGeo.onGeofence) regardless of this setting. Events that are not persisted are not eligible for HTTP uploads via HttpConfig.url.

The persist option on individual API calls can override this setting per-request:

let bgGeo = BGGeo.shared
Task {
    do {
        let location = try await bgGeo.getCurrentPosition(
            samples: 3,
            persist: true,
            extras: ["get_current_position": true]
        )
    } catch {
        print("[getCurrentPosition] error: \(error)")
    }
}

Examples
Now grouped under PersistenceConfig
let bgGeo = BGGeo.shared

bgGeo.config.batchUpdate { config in
    config.persistence.maxDaysToPersist = 14
    config.persistence.maxRecordsToPersist = 5000
    config.persistence.locationsOrderDirection = .ascending
    config.persistence.locationTemplate = "{...}"
    config.persistence.geofenceTemplate = "{...}"
    config.persistence.persistMode = .all
    config.persistence.extras = ["user_id": 123]
}
Configure persistence behavior
let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.maxDaysToPersist = 14
    config.persistence.maxRecordsToPersist = 5000
    config.persistence.locationsOrderDirection = .ascending
    config.persistence.persistMode = .all
    config.persistence.extras = ["user_id": 123, "appVersion": "1.2.3"]
    config.http.url = "https://example.com/locations"
    config.http.autoSync = true
}
Inspect and purge the database
let bgGeo = BGGeo.shared

let pending = bgGeo.store.count
print("Pending records: \(pending)")

// Purge all records
bgGeo.store.destroyAll()
print("Destroyed all records")
Custom JSON templates
let bgGeo = BGGeo.shared

bgGeo.config.batchUpdate { config in
    config.persistence.locationTemplate = """
    {
      "lat": <%= latitude %>,
      "lng": <%= longitude %>,
      "ts": "<%= timestamp %>"
    }
    """
    config.persistence.geofenceTemplate = """
    {
      "id": "<%= identifier %>",
      "action": "<%= action %>",
      "ts": "<%= timestamp %>"
    }
    """
}

Members

extras

public var extras: [String: Any]

Optional arbitrary key/value pairs merged into each recorded location at write time.

These values are persisted and included in all HTTP uploads, making them ideal for attaching static contextual metadata such as user_id, route_id, or session_id.

See also - HTTP Guide

let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.http.url = "https://my-server.com/locations"
    config.http.params = ["device_id": "abc123"]
    config.persistence.extras = ["route_id": 1234]
}

The resulting HTTP request body:

POST /locations
{
  "device_id": "abc123",
  "location": {
    "coords": {
      "latitude": 45.51927004945047,
      "longitude": -73.61650072045029
    },
    "extras": {
      "route_id": 1234
    }
  }
}

geofenceTemplate

public var geofenceTemplate: String

Optional custom ERB template for reshaping GeofenceEvent JSON in HTTP uploads.

Behaves like locationTemplate but includes two additional tags: geofence.identifier and geofence.action. Use Ruby-style ERB tags to interpolate field values:

<%= variable_name %>
let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.geofenceTemplate = "{ \"lat\":<%= latitude %>, \"lng\":<%= longitude %>, \"geofence\":\"<%= geofence.identifier %>:<%= geofence.action %>\" }"
}

// Or a compact Array form:
bgGeo.config.batchUpdate { config in
    config.persistence.geofenceTemplate = "[<%= latitude %>, <%= longitude %>, \"<%= geofence.identifier %>\", \"<%= geofence.action %>\"]"
}

Warning

The SDK does not automatically apply double-quotes around string data. Templates are JSON-encoded exactly as written.

Produces invalid JSON:

{"timestamp": 2018-01-01T12:01:01.123Z}
{"timestamp": "2018-01-01T12:01:01.123Z"}
Template tags

Identical to locationTemplate with the following additions:

Tag Type Description
geofence.identifier String Identifier of the activated geofence
geofence.action String "ENTER" or "EXIT"
latitude Float
longitude Float
speed Float Meters
heading Float Degrees
accuracy Float Meters
altitude Float Meters
altitude_accuracy Float Meters
timestamp String ISO-8601
uuid String Unique ID
event String motionchange, geofence, heartbeat, providerchange
odometer Float Meters
activity.type String still, on_foot, running, on_bicycle, in_vehicle, unknown
activity.confidence Integer 0–100%
battery.level Float 0–100%
battery.is_charging Boolean Whether device is plugged in
mock Boolean True when location was generated from a mock app
is_moving Boolean True if recorded while in moving state
timestampMeta Object Timestamp metadata; see GeolocationConfig.enableTimestampMeta

See also - locationTemplate - HttpConfig.rootProperty - HTTP Guide

Incorrect
let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.geofenceTemplate = "{\"timestamp\": <%= timestamp %>}"
}
Correct
let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.geofenceTemplate = "{\"timestamp\": \"<%= timestamp %>\"}"
}

locationTemplate

public var locationTemplate: String

Optional custom ERB template for reshaping LocationEvent JSON in HTTP uploads.

When set, the SDK evaluates the template string against each location record before serializing it. Use Ruby-style ERB tags to interpolate field values:

<%= variable_name %>
let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.locationTemplate = "{\"lat\":<%= latitude %>,\"lng\":<%= longitude %>,\"event\":\"<%= event %>\",isMoving:<%= is_moving %>}"
}

// Or use a compact Array template:
bgGeo.config.batchUpdate { config in
    config.persistence.locationTemplate = "[<%=latitude%>, <%=longitude%>, \"<%=event%>\", <%=is_moving%>]"
}

Warning

The SDK does not automatically insert quotes around string values. Templates are JSON-encoded exactly as written.

The following produces invalid JSON because timestamp is a string but is

let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.locationTemplate = "{\"timestamp\": <%= timestamp %>}"
}

This renders invalid JSON:

{"timestamp": 2018-01-01T12:01:01.123Z}
let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.persistence.locationTemplate = "{\"timestamp\": \"<%= timestamp %>\"}"
}
{"timestamp": "2018-01-01T12:01:01.123Z"}
Configured extras

If extras are configured, the key/value pairs are merged directly into the rendered location JSON.

let bgGeo = BGGeo.shared

bgGeo.ready { config in
    config.http.url = "https://my.server.com/locations"
    config.http.rootProperty = "data"
    config.persistence.locationTemplate = "{\"lat\":<%= latitude %>,\"lng\":<%= longitude %>}"
    config.persistence.extras = ["foo": "bar"]
}

Produces:

{
  "data": {
    "lat": 23.23232323,
    "lng": 37.37373737,
    "foo": "bar"
  }
}
Template tags
Tag Type Description
latitude Float
longitude Float
speed Float Meters
heading Float Degrees
accuracy Float Meters
altitude Float Meters
altitude_accuracy Float Meters
timestamp String ISO-8601
uuid String Unique ID
event String motionchange, geofence, heartbeat, providerchange
odometer Float Meters
activity.type String still, on_foot, running, on_bicycle, in_vehicle, unknown
activity.confidence Integer 0–100%
battery.level Float 0–100%
battery.is_charging Boolean Is device plugged in?
mock Boolean True if generated by mock provider
is_moving Boolean Device was moving when recorded
timestampMeta Object Timestamp metadata; see GeolocationConfig.enableTimestampMeta

See also - HTTP Guide - geofenceTemplate - HttpConfig.rootProperty

locationsOrderDirection

public var locationsOrderDirection:LocationsOrderDirection

Sort order used when selecting records for upload or returning them from BGGeo.getLocations. Defaults to "ASC" (oldest first).

  • "ASC" — oldest records first
  • "DESC" — newest records first

maxDaysToPersist

public var maxDaysToPersist: Int

Maximum number of days to retain a persisted record in the SDK's on-device SQLite database. Defaults to 1 day.

When your server fails to return a 20x response, the SDK continues retrying uploads. If a record remains unuploaded for longer than maxDaysToPersist days, it is permanently discarded to prevent unbounded database growth.

maxRecordsToPersist

public var maxRecordsToPersist: Int

Maximum number of records the SDK may retain in its on-device SQLite database. Defaults to -1 (no limit).

When a limit is set and the stored record count would exceed it, the oldest records are purged to make room for the newest.

See HttpEvent for details on upload behavior.

persistMode

public var persistMode:PersistMode

Controls which event types the SDK writes to its internal SQLite database. Defaults to PersistMode.All.

All recorded events are always delivered to their live callbacks (BGGeo.onLocation and BGGeo.onGeofence). This setting only determines what is written to persistent storage. Events that are not persisted are also not eligible for HTTP uploads via HttpConfig.url.

Value Description
PersistMode.All Default — persist both location and geofence events.
PersistMode.Location Persist location events only.
PersistMode.Geofence Persist geofence events only.
PersistMode.None Persist nothing.

Warning

This setting is intended for specialized cases. For example, if you need continuous location tracking via BGGeo.start but only want to store geofence events, configure persistMode: PersistMode.Geofence.