I got stuck when trying to keep my function running if I terminate the app.
Is it possible to keep core location (geofencing / geolocating) and core bluetooth running when app is not running ? If possible how to solve my issue? I already check the background modes, and implement core location method. this is my code :
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var viewController = ViewController()
var window: UIWindow?
var locationManager = CLLocationManager()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
locationManager = CLLocationManager()
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = false
if #available(iOS 9.0, *) {
locationManager.allowsBackgroundLocationUpdates = true
}
beaconRegion.notifyEntryStateOnDisplay = true
beaconRegion.notifyOnEntry = true
beaconRegion.notifyOnExit = true
locationManager.startMonitoring(for: beaconRegion)
locationManager.stopRangingBeacons(in: beaconRegion)
locationManager.startRangingBeacons(in: beaconRegion)
locationManager.startUpdatingLocation()
return true
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
if (region.identifier == beaconRegionIdentifier) {
manager.requestState(for: region)
goBackground()
}
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
print("you exited region")
}
func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
if (region.identifier == beaconRegionIdentifier) {
manager.stopUpdatingLocation()
switch state {
case .inside:
manager.startRangingBeacons(in: region as! CLBeaconRegion)
manager.startUpdatingLocation()
case .outside:
let delay = DispatchTime.now() + .seconds(3)
DispatchQueue.main.asyncAfter(deadline: delay) {
manager.requestState(for: region)
}
case .unknown:
let delay = DispatchTime.now() + .seconds(3)
DispatchQueue.main.asyncAfter(deadline: delay) {
manager.requestState(for: region)
}
}
}
}
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
let state = UIApplication.shared.applicationState
switch(state){
case.active,
.inactive,
.background:
let mainView = UserDefaults.standard.bool(forKey: "toMainView")
var isWakeUpRunning = UserDefaults.standard.bool(forKey: "isWakeUpRunning")
if isWakeUpRunning {
if mainView {
for aBeacon in beacons{
if aBeacon.rssi > WAKE_UP_THRESHOLD && aBeacon.rssi != 0{
UserDefaults.standard.set(false, forKey: "isWakeUpRunning")
self.viewController.startFunction()
manager.stopRangingBeacons(in: region)
}else if aBeacon.rssi != 0 && aBeacon.rssi < WAKE_UP_THRESHOLD {
manager.stopRangingBeacons(in: region)
manager.requestState(for: region)
}
}
}
}else{
manager.stopRangingBeacons(in: region)
manager.requestState(for: region)
}
}
}
func goBackground() {
let app = UIApplication.shared
var bgTask: UIBackgroundTaskIdentifier = 0
bgTask = app.beginBackgroundTask(expirationHandler: {
NSLog("Expired: %lu", bgTask)
app.endBackgroundTask(bgTask)
})
NSLog("Background: %lu", bgTask)
}
}
From my code, it can run in both in foreground and background. but when i swipe up the app from task switcher, it cannot work. and i cannot see the log too from xcode. Any ideas to help me ?