{"id":2253,"date":"2020-05-03T11:28:00","date_gmt":"2020-05-03T09:28:00","guid":{"rendered":"https:\/\/www.albertopasca.it\/whiletrue\/?p=2253"},"modified":"2023-06-26T15:57:31","modified_gmt":"2023-06-26T13:57:31","slug":"track-gps-position-with-ios-app-killed","status":"publish","type":"post","link":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/","title":{"rendered":"Track GPS position with iOS app killed"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I want to share a simple how-to, used to get the GPS position of an iOS user with the app completely closed, in the background, and in the foreground without using any useless workaround like idle timer and background operations&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We discuss about the <strong>GEO-fence<\/strong> tecnique. You can read more on Apple reference:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/developer.apple.com\/documentation\/corelocation\/monitoring_the_user_s_proximity_to_geographic_regions\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/developer.apple.com\/documentation\/corelocation\/monitoring_the_user_s_proximity_to_geographic_regions<\/a><\/p>\n\n\n\n<!--more-->\n\n\n\n<hr class=\"wp-block-separator has-text-color has-vivid-cyan-blue-color has-css-opacity has-vivid-cyan-blue-background-color has-background\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>I<\/strong>ntro<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">As iOS developer, you know that you can&#8217;t play with your app content when is closed. Partially true&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can execute some code with app completely closed only for these conditions:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Monitoring a geo-fence defined area<\/li>\n\n\n\n<li>Monitoring a defined bluetooth service <strong>CBUUID<\/strong> and communicate with it<\/li>\n\n\n\n<li>Receive iBeacon from bluetooth device<\/li>\n\n\n\n<li>Execute some code when receiving a push-notifications, also silently<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">In this tutorial, we discover the first point. See blog posts for the other points explained.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>H<\/strong>ow it works?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In order to use the GEO-fence you need to declare in your code the area you want to track. An area is a <strong>CLLRegion<\/strong> defined with a couple of coordinates (latitude and longitude) and a radius in meter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can define 250 max area.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You position tracking is managed now from the operating system and not from your app (because is closed&#8230;).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When your device enter (or exit) from a defined region, a callback in your code is called. In particular two delegates are called:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {}\nfunc locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If your app use the geo-fence, you should see in the status bar of your phone a new icon, like this, an empty arrow:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"309\" src=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1634.png?resize=1024%2C309\" alt=\"\" class=\"wp-image-2594\" srcset=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1634.png?resize=1024%2C309&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1634.png?resize=300%2C91&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1634.png?resize=768%2C232&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1634.png?w=1125&amp;ssl=1 1125w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"753\" height=\"1024\" src=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1635.png?resize=753%2C1024\" alt=\"\" class=\"wp-image-2593\" srcset=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1635.png?resize=753%2C1024&amp;ssl=1 753w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1635.png?resize=221%2C300&amp;ssl=1 221w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1635.png?resize=768%2C1044&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/IMG_1635.png?w=1125&amp;ssl=1 1125w\" sizes=\"auto, (max-width: 753px) 100vw, 753px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">And also your tracking mode should be setted to &#8220;<strong>EVER<\/strong>&#8220;.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>I<\/strong>nfinite geo-fence regions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To track the user location with the app closed, you need to play a little bit with the regions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A simple but very useful trick is to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>create a new <strong>CLRegion<\/strong> based on your current position when open the app<\/li>\n\n\n\n<li>in the <strong>didExit<\/strong> callback, create a new region with the position of the user in that moment<\/li>\n\n\n\n<li>in this way you can repeat this cycle forever<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s implementing this. An example is better.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-vivid-cyan-blue-color has-css-opacity has-vivid-cyan-blue-background-color has-background\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>G<\/strong>etting GPS position using geo-fence with app closed<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">Prepare your project<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Open <em>XCode<\/em>, create a new project and enable the <strong>Background Modes<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Location updates<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1552\" height=\"1030\" src=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/Schermata-2020-04-23-alle-10.18.01.png?fit=525%2C349&amp;ssl=1\" alt=\"\" class=\"wp-image-2548\" srcset=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/Schermata-2020-04-23-alle-10.18.01.png?w=1552&amp;ssl=1 1552w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/Schermata-2020-04-23-alle-10.18.01.png?resize=300%2C199&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/Schermata-2020-04-23-alle-10.18.01.png?resize=1024%2C680&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/Schermata-2020-04-23-alle-10.18.01.png?resize=768%2C510&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/Schermata-2020-04-23-alle-10.18.01.png?resize=1536%2C1019&amp;ssl=1 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">We also add some <strong>UNUserNotificationCenter<\/strong> in order to get notified when something with your app closed happened (like a notification-log). This because you cannot debug it&#8230; of course it&#8217;s closed.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-vivid-red-color has-css-opacity has-vivid-red-background-color has-background\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>I<\/strong>mplementing the <strong>UNUserNotificationCenter<\/strong> scheduler:<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create your extension, your manager, or place this code in the AppDelegate, a simple configuration for <strong>UNUserNotificationCenter<\/strong> scheduler:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">import UIKit\nimport UserNotifications\nextension AppDelegate: UNUserNotificationCenterDelegate {\n    \n    func registerNotifications() {\n        UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound]) { (granted:Bool, error:Error?) in\n            if error != nil { return }\n            DispatchQueue.main.async {\n                UIApplication.shared.registerForRemoteNotifications()\n            }\n        }\n        UNUserNotificationCenter.current().delegate = self\n    }\n        \n    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -&gt; Void) {\n        completionHandler([.alert, .badge, .sound])\n    }\n    \n    func scheduleLocalNotification(alert:String) {\n        let content = UNMutableNotificationContent()\n        let requestIdentifier = UUID.init().uuidString\n        \n        content.badge = 0\n        content.title = \"Location Update\"\n        content.body = alert\n        content.sound = UNNotificationSound.default\n        \n        let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 1.0, repeats: false)       \n        let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)\n        UNUserNotificationCenter.current().add(request) { (error:Error?) in            \n            print(\"Notification Register Success\")\n        }\n    }\n    \n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We have now the notification scheduler configured.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Come back in the <em>AppDelegate<\/em> and in the <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; Bool { }<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Call the <strong>registerNotifications()<\/strong> method. You&#8217;ll receive a privacy alert that informs you that the app wants to send push notifications.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Make a test, should works as expected.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-vivid-red-color has-css-opacity has-vivid-red-background-color has-background\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>I<\/strong>mplementing the <strong>CoreLocation<\/strong> manager:<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">As before, create a new manager or copy\/paste to your AppDelegate.swift if you prefer. This class is responsible of getting authorization and GPS position of the user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">import UIKit\nimport CoreLocation\nextension AppDelegate: CLLocationManagerDelegate {\n    \n    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {\n        if status == .authorizedAlways || status == .authorizedWhenInUse {\n            manager.startUpdatingLocation()\n        }\n    }\n    \n    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {\n        let location = locations.last\n        if (location?.horizontalAccuracy)! &lt;= Double(65.0) {\n            myLocation = location\n            print (\"we add something later...\")\n        } else {\n            manager.stopUpdatingLocation()\n            manager.startUpdatingLocation()\n        }\n    }\n    \n    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {\n        scheduleLocalNotification(alert: \"didEnterRegion\")\n    }\n    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {\n        scheduleLocalNotification(alert: \"didExitRegion\")\n        manager.stopMonitoring(for: region)\n        manager.startUpdatingLocation()\n    }\n    \n    func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {\n        scheduleLocalNotification(alert: error.localizedDescription)\n    }\n    \n    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {\n        scheduleLocalNotification(alert: error.localizedDescription)\n    }\n    \n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Well, we have also the <strong>CoreLocation<\/strong> manager ready to use.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can instanciate in your class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">var locationManager: CLLocationManager? = CLLocationManager()<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-vivid-cyan-blue-color has-css-opacity has-vivid-cyan-blue-background-color has-background\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>M<\/strong>anaging the CLRegion(s)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve created an helper function to create your <strong>CLRegion<\/strong>, this one:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">func createRegion(location:CLLocation?) {\n    if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {\n        let coordinate = CLLocationCoordinate2DMake((location.coordinate.latitude), (location.coordinate.longitude))\n        let regionRadius = 100.0\n        let coords = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)\n        let region = CLCircularRegion(center: coords, radius: regionRadius, identifier: \"aabb\")\n        region.notifyOnEntry = true\n        region.notifyOnExit  = false\n        scheduleLocalNotification(alert: \"Region Created \\(location.coordinate) with \\(location.horizontalAccuracy)\")\n        self.locationManager?.stopUpdatingLocation()\n        self.locationManager?.startMonitoring(for: region)\n    }\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To make it works you should also implement the CoreLocation manager and a custom CLLocation (the user position):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">var locationManager: CLLocationManager? = CLLocationManager()\nvar myLocation: CLLocation?\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now, go in your <code>didFinishLaunchingWithOptions<\/code> and initialize the <code>locationManager<\/code> controlling the status of the application with <code>launchOptions<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">if launchOptions?[UIApplication.LaunchOptionsKey.location] != nil {\n    if locationManager == nil {\n        locationManager = CLLocationManager()\n    } else {\n        locationManager = nil\n        locationManager = CLLocationManager()\n    }\n    locationManager?.delegate = self\n    locationManager?.distanceFilter = 10\n\tlocationManager?.desiredAccuracy = kCLLocationAccuracyBest\n    locationManager?.allowsBackgroundLocationUpdates = true\n    locationManager?.startUpdatingLocation()\n} else {\n    locationManager?.delegate = self\n    locationManager?.distanceFilter = 10\n    locationManager?.desiredAccuracy = kCLLocationAccuracyBest\n    locationManager?.allowsBackgroundLocationUpdates = true\n    if CLLocationManager.authorizationStatus() == .notDetermined {\n        locationManager?.requestAlwaysAuthorization()\n    }\n    else if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {\n        locationManager?.requestAlwaysAuthorization()\n    }\n    else if CLLocationManager.authorizationStatus() == .authorizedAlways {\n        locationManager?.startUpdatingLocation()\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We start and restart the location and check also the authorization status.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the status is <code>authorizedAlways<\/code> we can start monitoring the locations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Another important this is to create your region when the app enter in background (before closing):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">func applicationDidEnterBackground(_ application: UIApplication) {\n    self.createRegion(location: myLocation)\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">One more thing, replace the line &#8220;we add something later&#8221; with the creation of a region, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"swift\" class=\"language-swift\">if !(UIApplication.shared.applicationState == .active) {\n    self.createRegion(location: location)\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now you have the updated position every time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also call an API instead of launching notifications of course. Notifications are useful to &#8220;debug&#8221; without debug attached.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">Remember also to add in the <strong>Info.plist<\/strong> the privacy settings (else the app crash on startup):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"xml\" class=\"language-xml\">&lt;key&gt;NSLocationAlwaysAndWhenInUseUsageDescription&lt;\/key&gt;\n&lt;string&gt;App wants to use location in background&lt;\/string&gt;\n&lt;key&gt;NSLocationAlwaysUsageDescription&lt;\/key&gt;\n&lt;string&gt;App wants to use location in background&lt;\/string&gt;\n&lt;key&gt;NSLocationWhenInUseUsageDescription&lt;\/key&gt;\n&lt;string&gt;App wants to use location in background&lt;\/string&gt;<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">Now you can run the app and accept all the popups that you receive:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>push notifications<\/li>\n\n\n\n<li>gps position always<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Your app is tracking now. If you go out with your phone you receive lots of notifications that inform you that the position is changed and a new <em>CLRegion<\/em> is created. Infinitely.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In a few days, you&#8217;ll receive a new system popup that informs you that the app wants to use your GPS location when is closed. Remember to select &#8220;<strong>Always Allow<\/strong>&#8220;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"473\" height=\"1024\" src=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?resize=473%2C1024\" alt=\"\" class=\"wp-image-2641\" srcset=\"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?resize=473%2C1024&amp;ssl=1 473w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?resize=139%2C300&amp;ssl=1 139w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?resize=768%2C1663&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?resize=709%2C1536&amp;ssl=1 709w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?resize=946%2C2048&amp;ssl=1 946w, https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?w=1125&amp;ssl=1 1125w\" sizes=\"auto, (max-width: 473px) 100vw, 473px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">If you add some API and send data to a remote DB you can analyze the user locations and make a map with polylines.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enjoy tracking.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I want to share a simple how-to, used to get the GPS position of an iOS user with the app completely closed, in the background, and in the foreground without using any useless workaround like idle timer and background operations&#8230; We discuss about the GEO-fence tecnique. You can read more on Apple reference: https:\/\/developer.apple.com\/documentation\/corelocation\/monitoring_the_user_s_proximity_to_geographic_regions<\/p>\n","protected":false},"author":1,"featured_media":2641,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1],"tags":[929,936,931,816,934,935,930,616,932,933,937],"class_list":["post-2253","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-generic","tag-app-killed","tag-background-modes","tag-clregion","tag-corelocation","tag-didenterregion","tag-didexitregion","tag-geo-gence","tag-gps","tag-ibeacon","tag-position","tag-unusernotificationcenter"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Track GPS position with iOS app killed - while (true) {\u00a0}<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Track GPS position with iOS app killed - while (true) {\u00a0}\" \/>\n<meta property=\"og:description\" content=\"I want to share a simple how-to, used to get the GPS position of an iOS user with the app completely closed, in the background, and in the foreground without using any useless workaround like idle timer and background operations&#8230; We discuss about the GEO-fence tecnique. You can read more on Apple reference: https:\/\/developer.apple.com\/documentation\/corelocation\/monitoring_the_user_s_proximity_to_geographic_regions\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/\" \/>\n<meta property=\"og:site_name\" content=\"while (true) {\u00a0}\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-03T09:28:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-26T13:57:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654-473x1024.png\" \/>\n\t<meta property=\"og:image:width\" content=\"473\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Alberto Pasca\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@lupasca\" \/>\n<meta name=\"twitter:site\" content=\"@lupasca\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alberto Pasca\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/\"},\"author\":{\"name\":\"Alberto Pasca\",\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/#\\\/schema\\\/person\\\/d3cf0df774eb4aac797f246a795e9fac\"},\"headline\":\"Track GPS position with iOS app killed\",\"datePublished\":\"2020-05-03T09:28:00+00:00\",\"dateModified\":\"2023-06-26T13:57:31+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/\"},\"wordCount\":776,\"publisher\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/#\\\/schema\\\/person\\\/d3cf0df774eb4aac797f246a795e9fac\"},\"image\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.albertopasca.it\\\/whiletrue\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/img_1654.png?fit=1125%2C2436&ssl=1\",\"keywords\":[\"app killed\",\"background modes\",\"clregion\",\"corelocation\",\"didEnterRegion\",\"didExitRegion\",\"geo gence\",\"gps\",\"ibeacon\",\"position\",\"UNUserNotificationCenter\"],\"articleSection\":[\"generic\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/\",\"url\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/\",\"name\":\"Track GPS position with iOS app killed - while (true) {\u00a0}\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.albertopasca.it\\\/whiletrue\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/img_1654.png?fit=1125%2C2436&ssl=1\",\"datePublished\":\"2020-05-03T09:28:00+00:00\",\"dateModified\":\"2023-06-26T13:57:31+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.albertopasca.it\\\/whiletrue\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/img_1654.png?fit=1125%2C2436&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.albertopasca.it\\\/whiletrue\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/img_1654.png?fit=1125%2C2436&ssl=1\",\"width\":1125,\"height\":2436},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/track-gps-position-with-ios-app-killed\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Track GPS position with iOS app killed\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/#website\",\"url\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/\",\"name\":\"while (true) {\u00a0}\",\"description\":\"notes from a developer, tutorials, how-to, ideas\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/#\\\/schema\\\/person\\\/d3cf0df774eb4aac797f246a795e9fac\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.albertopasca.it\\\/whiletrue\\\/#\\\/schema\\\/person\\\/d3cf0df774eb4aac797f246a795e9fac\",\"name\":\"Alberto Pasca\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g\",\"caption\":\"Alberto Pasca\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g\"},\"description\":\"Software engineer @ Pirelli &amp; C. S.p.A. with a strong passion for mobile \uf8ff development, security, and connected things.\",\"sameAs\":[\"https:\\\/\\\/www.albertopasca.it\",\"albertopasca\",\"https:\\\/\\\/x.com\\\/lupasca\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Track GPS position with iOS app killed - while (true) {\u00a0}","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/","og_locale":"en_US","og_type":"article","og_title":"Track GPS position with iOS app killed - while (true) {\u00a0}","og_description":"I want to share a simple how-to, used to get the GPS position of an iOS user with the app completely closed, in the background, and in the foreground without using any useless workaround like idle timer and background operations&#8230; We discuss about the GEO-fence tecnique. You can read more on Apple reference: https:\/\/developer.apple.com\/documentation\/corelocation\/monitoring_the_user_s_proximity_to_geographic_regions","og_url":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/","og_site_name":"while (true) {\u00a0}","article_published_time":"2020-05-03T09:28:00+00:00","article_modified_time":"2023-06-26T13:57:31+00:00","og_image":[{"width":473,"height":1024,"url":"https:\/\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654-473x1024.png","type":"image\/png"}],"author":"Alberto Pasca","twitter_card":"summary_large_image","twitter_creator":"@lupasca","twitter_site":"@lupasca","twitter_misc":{"Written by":"Alberto Pasca","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/#article","isPartOf":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/"},"author":{"name":"Alberto Pasca","@id":"https:\/\/www.albertopasca.it\/whiletrue\/#\/schema\/person\/d3cf0df774eb4aac797f246a795e9fac"},"headline":"Track GPS position with iOS app killed","datePublished":"2020-05-03T09:28:00+00:00","dateModified":"2023-06-26T13:57:31+00:00","mainEntityOfPage":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/"},"wordCount":776,"publisher":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/#\/schema\/person\/d3cf0df774eb4aac797f246a795e9fac"},"image":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?fit=1125%2C2436&ssl=1","keywords":["app killed","background modes","clregion","corelocation","didEnterRegion","didExitRegion","geo gence","gps","ibeacon","position","UNUserNotificationCenter"],"articleSection":["generic"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/","url":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/","name":"Track GPS position with iOS app killed - while (true) {\u00a0}","isPartOf":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/#primaryimage"},"image":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?fit=1125%2C2436&ssl=1","datePublished":"2020-05-03T09:28:00+00:00","dateModified":"2023-06-26T13:57:31+00:00","breadcrumb":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/#primaryimage","url":"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?fit=1125%2C2436&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?fit=1125%2C2436&ssl=1","width":1125,"height":2436},{"@type":"BreadcrumbList","@id":"https:\/\/www.albertopasca.it\/whiletrue\/track-gps-position-with-ios-app-killed\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.albertopasca.it\/whiletrue\/"},{"@type":"ListItem","position":2,"name":"Track GPS position with iOS app killed"}]},{"@type":"WebSite","@id":"https:\/\/www.albertopasca.it\/whiletrue\/#website","url":"https:\/\/www.albertopasca.it\/whiletrue\/","name":"while (true) {\u00a0}","description":"notes from a developer, tutorials, how-to, ideas","publisher":{"@id":"https:\/\/www.albertopasca.it\/whiletrue\/#\/schema\/person\/d3cf0df774eb4aac797f246a795e9fac"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.albertopasca.it\/whiletrue\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.albertopasca.it\/whiletrue\/#\/schema\/person\/d3cf0df774eb4aac797f246a795e9fac","name":"Alberto Pasca","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g","caption":"Alberto Pasca"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/4d8fe43c412d0bb34a71c41f60dce53eff3afc027853cbfd20bee6ddc7e93f35?s=96&d=retro&r=g"},"description":"Software engineer @ Pirelli &amp; C. S.p.A. with a strong passion for mobile \uf8ff development, security, and connected things.","sameAs":["https:\/\/www.albertopasca.it","albertopasca","https:\/\/x.com\/lupasca"]}]}},"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.albertopasca.it\/whiletrue\/wp-content\/uploads\/2020\/04\/img_1654.png?fit=1125%2C2436&ssl=1","_links":{"self":[{"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/posts\/2253","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/comments?post=2253"}],"version-history":[{"count":109,"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/posts\/2253\/revisions"}],"predecessor-version":[{"id":3397,"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/posts\/2253\/revisions\/3397"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/media\/2641"}],"wp:attachment":[{"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/media?parent=2253"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/categories?post=2253"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.albertopasca.it\/whiletrue\/wp-json\/wp\/v2\/tags?post=2253"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}