I’ve applied geofencing to detect the entry and exit from the area. It appears working tremendous when the app is in a foreground/background/terminated state initially. I’m testing this performance utilizing GPX. When an app is terminated, I get entry exit notifications too. However I’ve noticed that in lots of situations when an app is suspended or terminated for an extended time frame, Regardless that the consumer is getting into and leaving the area, No notifications are triggered. After I open the app manually, I can see the entry,or exit notifications immediately.
Right here is my code snippet.
class LocationService: NSObject, CLLocationManagerDelegate {
static let sharedInstance: LocationService = { LocationService()
}()
var locationManager: CLLocationManager?
var startLocation: CLLocation?
var lastLocation: CLLocation?
var delegate: LocationServiceDelegate?
var isAuthorized: ((Bool) -> Void)?
var boolSendUpdate = false
var locationTimer = Timer()
var isFirstTime:Bool!
override init() {
tremendous.init()
self.locationManager = CLLocationManager()
guard let locationManager = self.locationManager else {
return
}
//locationManager.desiredAccuracy = kCLLocationAccuracyBest // The accuracy of the placement knowledge
locationManager.delegate = self
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.allowsBackgroundLocationUpdates = true// if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self){
// print("Out there")
// }
//
NotificationCenter.default.addObserver(self, selector:#selector(startUpdatingLocation), title: UIApplication.didBecomeActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(stopUpdatingLocation), title: UIApplication.willTerminateNotification, object: nil)
}
func checkPermission(isAuthorized: ((Bool) -> Void)? = nil) {
guard let locationManager = self.locationManager else {
return
}
change(CLLocationManager.authorizationStatus()) {
case .authorizedAlways,.authorizedWhenInUse:
self.startUpdatingLocation()
isAuthorized?(true)
// get the consumer location
case .restricted, .denied:
isAuthorized?(false)
// redirect the customers to settings
popupAlert(title: NSLocalizedString("settings", remark: ""), message:go_to_settings, actionTitles: [NSLocalizedString("Cancel", comment: ""),NSLocalizedString("Settings", comment: "")], actions:[{action1 in
},{action2 in
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
return
}
if UIApplication.shared.canOpenURL(settingsUrl) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in })
}
}, nil])
case .notDetermined:
isAuthorized?(false)
locationManager.requestWhenInUseAuthorization()
@unknown default:
isAuthorized?(false)
locationManager.requestWhenInUseAuthorization()
}
}
@objc func startUpdatingLocation() {
self.locationManager?.startUpdatingLocation()
self.locationManager?.requestAlwaysAuthorization()
}
@objc func stopUpdatingLocation() {
if !CLLocationManager.significantLocationChangeMonitoringAvailable() {
return
}
self.locationManager?.stopUpdatingLocation()
self.locationManager?.startMonitoringSignificantLocationChanges()
}
func setUpGeofenceing(location:CLLocation,identifier:String = "",radius:CLLocationDistance,standing:enumShiftStatus) {
let geofenceRegionCenter = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let geofenceRegion = CLCircularRegion.init(middle: geofenceRegionCenter, radius: radius, identifier: identifier)
geofenceRegion.notifyOnExit = true
geofenceRegion.notifyOnEntry = true
if !CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
print("Geofencing will not be supported on this machine!")
UIApplication.shared.home windows.first?.rootViewController?.presentAlert(withTitle:"MetroOne Officer", message: "Geofencing will not be supported on this machine!")
return
}
if locationManager?.monitoredRegions.comprises(geofenceRegion) == false {
locationManager?.startMonitoring(for: geofenceRegion)
}
}
func stopGeoFenceing(identifier: String = ""){
}
// CLLocationManagerDelegate
func locationManager(_ supervisor: CLLocationManager, didChangeAuthorization standing: CLAuthorizationStatus) {
guard let delegate = self.delegate else {
return
}
delegate.didChangeAuthorization(standing: standing)
}
func locationManager(_ supervisor: CLLocationManager, didUpdateLocations areas: [CLLocation]) {
guard let location = areas.final else {
return
}
// singleton for get final location
self.lastLocation = location
// use for actual time replace location
updateLocation(currentLocation: location)
}
func locationManager(_ supervisor: CLLocationManager, didFailWithError error: Error) {
// do on error
updateLocationDidFailWithError(error: error as NSError)
}
func locationManager(_ supervisor: CLLocationManager, didStartMonitoringFor area: CLRegion) {
debugPrint("Began Monitoring for Area:::",area.description)
guard #out there(iOS 14, *) else {
self.locationManager?.requestState(for:area)
return
}
}
func locationManager(_ supervisor: CLLocationManager, monitoringDidFailFor area: CLRegion?, withError error: Error) {
debugPrint("error::(error.localizedDescription)")
}
// Non-public operate
personal func updateLocation(currentLocation: CLLocation){
guard let delegate = self.delegate else {
return
}
delegate.tracingLocation(currentLocation: currentLocation)
}
personal func updateLocationDidFailWithError(error: NSError) {
guard let delegate = self.delegate else {
return
}
delegate.tracingLocationDidFailWithError(error: error)
}
func locationManager(_ supervisor: CLLocationManager, didDetermineState state: CLRegionState, for area: CLRegion) {
change state {
case .inside:
postApiGeoFenceEntries(sort: RegionType.In.rawValue, shiftStatus: enumShiftPostStatus.CheckIn.rawValue)
case .exterior:
postApiGeoFenceEntries(sort: RegionType.Out.rawValue, shiftStatus: enumShiftPostStatus.CheckOut.rawValue)
case .unknown:
print("Unknown")
default:
print("Default")
}
}
}
App delegate code snippet.
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
var window: UIWindow?
func software(_ software: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override level for personalisation after software launch
if launchOptions?[UIApplication.LaunchOptionsKey.location] != nil {
_ = LocationService.sharedInstance
UNUserNotificationCenter.present().delegate = self
}
return true
}
}
I’ve additionally enabled location updates in capabilities. Please let me know if I’m lacking one thing.
Thanks.