01. How to use iOS Geofencing in your business?

It will take about 10 minutes to finish reading this article.

Here is a summary of all the possible reasons for publishing failure in Hexo.

1. Background

There was once such a requirement scenario, when the user walks into the neighborhood of a shop, we can send the user and the shop related to the push message, so as to attract traffic for the business. This kind of requirement is actually very common, especially for local life business.

For this kind of requirement, the more common solution is to continuously obtain the latitude and longitude of the user’s current location and report it to the back-end, which will then calculate and determine whether the user has entered the area that has been marked out in advance, and if he/she has entered the area, then send a remote notification to the user.

Since the business was brand new, the service side downgraded the priority of this project due to manpower constraints and it could not be scheduled until a long time. At the same time, our product manager had some urgent needs to support this feature. After discussion, we prioritized Region Monitoring on iOS, and the service side only needed to spare less manpower to support it.

Therefore, Core Location provided Region Monitoring to realize this requirement, which was a temporary solution and depended too much on the client-side logic, but for a brand new business, a lot of things needed to be verified with less cost, so Region Monitoring played its role at this time.

This article was briefly written years ago:

https://leon0206.blog.csdn.net/article/details/54670446

This time it is part of a content update.

2. Principles of Geofencing

2.1 Prerequisites
The Geofencing feature is a sub-function of CLLocationManager, so its trigger callbacks are also in the callbacks of CLLocationManagerDelegate. If you want to trigger these callbacks, you need to meet some of the conditions, in the official Apple documentation is also introduced, you need to meet the following conditions before you can use it:

To summarize:

(1) The user’s phone has the hardware required for area monitoring (GPS, sufficient battery, Wifi, etc.);

(2) The user has enabled location-related services (“Always” or “When in use” permission, background application refresh, etc.);

Of course we can call CLLocationManager’s isMonitoringAvailableFor: class method and authorizationStatus() to tell the availability of the Region Monitoring feature.

1
2
3
if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
// Circular geofence monitoring is available
}
1
2
3
4
let authorizationStatus = CLLocationManager.authorizationStatus()
if authorizationStatus == .authorizedAlways {
// Authorized to access location information at all times
}

2.2 CLCircularRegion

Geofencing monitoring starts with setting up a circle to monitor, which is defined as a CLCircularRegion with a center coordinate and a radius in meters, and an identifier as the key value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
open class CLCircularRegion : CLRegion {


/*
* initWithCenter:radius:identifier:
*
* Discussion:
* Initialize a region. center gives the coordinates of center of the region, while radius gives
* the distance in meters between the center and the region's boundary. identifier is a description
* for the region that could be displayed to the user, and ideally should be chosen by the user.
*/
public init(center: CLLocationCoordinate2D, radius: CLLocationDistance, identifier: String)
...
}

Note: identifier is the unique identifier of the region, if the added region has the same identifier, the new region will replace the old one.

2.3 Registered Area Monitors

For a Region to be monitored, it first needs to be registered and an already registered Region can also be stopped.

1
2
func startMonitoring(for region: CLRegion)
func stopMonitoring(for region: CLRegion)

2.4 Region Monitor

When iOS devices can listen for users entering or leaving a circular fence area. The entrance event fires when the user moves from outside the circle to inside the circle.

At the same time, the exit event fires when the user leaves the circular area, as shown in the following figure:

Note 1:
After registering an area, you can start monitoring immediately, but you won’t receive the event immediately, because the event must be triggered by “boundary crossings”, that is, you have to cross into or out of an area to trigger the event, and the corresponding callback function will be triggered as well:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
if let circularRegion = region as? CLCircularRegion {
handleRegionEvent(circularRegion)
}
}

func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
if let circularRegion = region as? CLCircularRegion {
handleRegionEvent(circularRegion)
}
}

func handleRegionEvent(_ region: CLCircularRegion) {
// Code to handle entry or exit zone events
}

Note 2:

You can use the CLLocationManager’s Request Status Information for Specified Region method to check if the user is already in a region:

1
2
// Request state information for the specified region
locationManager.requestState(for: region)

When a user enters or leaves the monitored area, if the app is not executing, the app will be relaunched in Backgroud to handle the triggered entry and exit actions.

If the app is suspended in the background, the app will be wokenup for a short period of time (about 10 seconds, more background execution time can be requested if necessary).

Careful people must think, if there is a user in the boundary of the non-stop “wandering”, will not always start callbacks, for this case, Apple also has a corresponding solution, as follows:

The explanation is:

Region events may not occur immediately after a region boundary is crossed. To prevent false notifications, iOS does not send region notifications until a specific threshold condition is met. Specifically, the user’s location must cross the region boundary, be a minimum distance away from the boundary, and maintain that minimum distance for at least 20 seconds before a notification is sent.

2.5 Demo

Here we look at a demo demo, this demo is the code address has been noted below, you can download.

(1) in the map area register a center for 31.239394,121.499781, radius of 2000 meters of the area, as follows:

(2) Change the location of the analog positioning to 31.259394,121.499781 as follows:

(3) At this time we again change the current location latitude and longitude to: 31.240394,121.499781, has entered the detected area, as follows:

(4) Similarly, if we cut the app to the background or kill it and change the current location, we can still receive local local notifications as follows:

2.6 Regions limit

Apple’s official document points out that each app can monitor up to 20 regions, and the monitored regions are shared system resources, while the number of monitoring provided by the whole system is limited. For this limitation, one strategy given by Apple is to set different regions according to the user’s current location, and after the user changes the location, remove the far away region and set a new region. If you go beyond 20 and continue to add, a fail callback will be executed to you:

1
2
3
4
5

- (void)locationManager:(CLLocationManager *)manager
monitoringDidFailForRegion:(nullable CLRegion *)region
withError:(NSError *)error {}

3. Application of business scenarios

How to use the specific also need to be based on business scenarios to decide, I suggest the following based on our previous business dynamics (this should be the most complex scenarios):

(1) Server-side distribution strategy of Regions

A user’s path we can not predict, so the Regions should take a hierarchical trigger. For example, the first to send a few default province-level large Regions (Zhejiang, Jiangsu, Anhui, etc.), if the user triggers one of the Region (Zhejiang), then you can dynamically update the Regions again for the city-level Region in Zhejiang Province, the next time you trigger a city (Hangzhou) of the Region, you can once again update the regional level of the Region. Region…

(2) Note that the specific implementation of

Regions need to be cached (expiration time), the interface needs to be issued Regions trigger strategy to avoid redundant startup requests; Regions identifier to avoid duplication, if it involves multiple businesses, it is best to distinguish the prefixes; Regions if the trigger is not needed, please stop; Regions monitor is recommended to have a global switch, the next time the trigger is a city (Hangzhou) Region, you can update the region again. monitor suggests that there is a global switch, you can server-side control off and on.

4. Cautions

Firstly, Turning on this feature will set off the background refresh of the app, and the app will become very power-consuming (LocationManager itself is very power-consuming), which may not be a good experience for the user; so you need to be careful to turn on this feature, turn it on in time, and the related parameters (location accuracy precision and monitor’s radius) need to be more refined.

Secondly, Region monitor, like some Push services, will wake up the app in not running or suspend state to backgroud state, during which it will execute the application:didFinishLaunchingWithOptions: method in AppDelegate. : method, the following implications may exist here:

(1) If your application adds a large code base to didFinishLaunching without categorizing the application launching scenarios, there may be some problems. For example, your logging system may record this as a cold launch event, which will affect your user activity statistics.

(2) Because the app may only exist in backgroud state and does not need to load all the codebase, it is recommended to optimize it in separate scenarios from the point of view of sex consumption.

(3) Here is a test demo for the OC version of RW: https://github.com/942v/Geotify-RW.

Reference

[1] https://www.kodeco.com/17649843-geofencing-with-core-location-getting-started
[2] https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html