Setup¶
Installation¶
Swift Package Manager is the only supported installation method.
In Xcode: File → Add Package Dependencies, enter the repository URL:
Select Up to Next Major Version from the latest release, then add the BackgroundGeolocation library to your target.
Configure your license¶
Purchase a license
The SDK requires a license for release builds. Debug builds work without one. Purchase at transistorsoft.com.
Add your license key to Info.plist:
Info.plist¶
Background Modes¶
<key>UIBackgroundModes</key>
<array>
<string>location</string>
<string>fetch</string>
<string>processing</string>
<string>audio</string>
</array>
Background Task Identifiers¶
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.transistorsoft.fetch</string>
</array>
Location Usage Descriptions¶
iOS requires a human-readable explanation for each level of location access your app requests.
<!-- Location usage descriptions -->
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>App requires location access at all times for background tracking.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>App requires location access while in use.</string>
<key>NSMotionUsageDescription</key>
<string>Motion detection helps determine when the device is stationary.</string>
Example¶
import SwiftUI
import BackgroundGeolocation
@main
struct MyApp: App {
private var subscriptions = Set<BGGeo.EventSubscription>()
init() {
let bgGeo = BGGeo.shared
// Register event listeners *before* calling ready()
bgGeo.onLocation { event in
print("[onLocation] \(event.coords)")
}.store(in: &subscriptions)
// ready() configures the SDK and restores persisted state.
// It does NOT start tracking — call start()/stop() separately.
bgGeo.ready { config in
config.geolocation.desiredAccuracy = kCLLocationAccuracyBest
config.geolocation.distanceFilter = 10
config.app.stopOnTerminate = false
config.app.startOnBoot = true
config.logger.debug = true
config.logger.logLevel = .verbose
}
}
var body: some Scene {
WindowGroup { ContentView() }
}
}
// Elsewhere — e.g. a toggle-button action in your UI
struct TrackingButton: View {
@State private var isTracking = BGGeo.shared.state.enabled
var body: some View {
Button(isTracking ? "Stop" : "Start") {
Task {
let bgGeo = BGGeo.shared
if isTracking {
bgGeo.stop()
} else {
try await bgGeo.start()
}
isTracking = bgGeo.state.enabled
}
}
}
}