The ability to detect whether a user has entered a specific geographic location is a useful feature that was added to iOS in version 4. There are several aspects to creating a monitored region (geofence) that I’m going to go over in a series of tutorials. In this tut we create a core location region object to act as the geo fence, then we monitor that region to see if the user enters or exits, in the sample code there’s an example of how a notification is fired even if the application is not running.
Firstly we create a CLRegion Object, this is made up of three parts, location (long/lat), radius (size of the geofence), and identifier (NSString name). In the example project I’m storing the regions as JSON, this could be loaded dynamically from a server and download them at runtime, but for this tutorial we’ll just hardcode one. Make sure you’ve imported the
This method returns a CLRegion object from a dictionary with keys: longitude, latitude, radius and title.
- (CLRegion*)mapDictionaryToRegion:(NSDictionary*)dictionary { NSString *title = [dictionary valueForKey:@"title"]; CLLocationDegrees latitude = [[dictionary valueForKey:@"latitude"] doubleValue]; CLLocationDegrees longitude =[[dictionary valueForKey:@"longitude"] doubleValue]; CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude); CLLocationDistance regionRadius = [[dictionary valueForKey:@"radius"] doubleValue]; return [[CLRegion alloc] initCircularRegionWithCenter:centerCoordinate radius:regionRadius identifier:title]; }
We then need to start monitoring the geofences using the aptly named startMonitoringForRegion: method. So assuming we’d created multiple regions in an array, we’d cycle through them like so:
for(CLRegion *geofence in geofences) { [_locationManager startMonitoringForRegion:geofence]; }
and then we handle the entry and exit using the didEnterRegion: and didExitRegion: methods
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { NSLog(@"Exited Region - %@", region.identifier); // post a notification } - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { NSLog(@"Exited Region - %@", region.identifier); // post a notification }
It’s that simple. There are a number of things to take into account when creating a geofence enabled app:
1. There are a limited number of regions that can be monitored by the phone at anyone time, and each app is limited to 20 regions. You should only register regions that are in the users immediate vicinity. However regions can be switched on off and new ones added dynamically based on your position, so for most applications this should be fine. If you attempt to register a region and space is unavailable the delegate method locationManager:monitoringDidFailForRegion:withError: will be called.
2. Regions must have unique identifiers otherwise the older region will be replaced by the newer one.
3. An app can register up to 20 regions at a time.
4. In order to report region changes in a timely manner, the region monitoring service requires network connectivity.
5. Regarding a region’s radius and accuracy, I’ve set radii to 20 meters and found them to be accurate to about half a NYC block. This could also have to do with latency from mobile phone tower connections, other related geo location/maps inaccuracies and the pace of my walking. The docs do mention a time lag when a user enters a region, apparently the app checks to make sure they have fully entered the region before updating, so as not to continually update if the users is positioned o the edge of a region. Although the docs mention a time lag of between 2-5 minutes, I have found the notification to be much more accurate. The best way to find out is to do a bit of on the ground testing in the desired location. From Apple’s docs: “In iOS 6, regions with a radius between 1 and 400 meters work better on iPhone 4S or later devices. (In iOS 5, regions with a radius between 1 and 150 meters work better on iPhone 4S and later devices.) On these devices, an app can expect to receive the appropriate region entered or region exited notification within 3 to 5 minutes on average, if not sooner.”
6. Before implementing any type of Core Location service we should check to see if Core Location services are available. The user may have disabled location services for this app or altogether in Settings, or may be in airplane mode.
7. Monitoring of regions happens instantaneously, however only occurs if the user has entered or exited a region, so if they are alrady in the region a notification will not be sent.
For more information check out Apple’s Core Location documentation here
sabir
How can i add geo fencing location from my application.Am very new to geo fencing as per your tutorial your telling like your fetching the latitude and longitude and other required fields from server .
My question is where user can register geo fencing region and is it any way to register from application.
Thanks
shabeer
samkeeneinteractivedesign@gmail.com
Hey Shabeer,
Thanks for reading the tut, and thanks for the comment.
If you look at the example project on GitHub I’m not actually pulling the longs and lats from a server (although you could do this and it is why I set the project up the way I did), but from a .plist in the project bundle, take a look at it here. This plist contains all the info you need to register a CLRegion (and then some), so you would only need to update this file with your longs and lats. You’ll notice the method at line 40 buildGeofenceData is pulling in this plist, cycling through it and creating CLRegion objects from it. Another, simpler way to do all this would be to bypass the mapDictionaryToRegion method at line 77 and hardcode your own CLRegion objects using all of your longs and lats. I hope this answers your question.
sabir
Hi
I have downloaded your sample project and i have added my location lat and long in plist .
when am walking inside that region i didnt get any notification .i kept radius 10 and am giving difference lat and long max in 30 meters.ca you please help me to slove this issue
samkeeneinteractivedesign@gmail.com
Make sure you fully exit the region. This could be the problem. You need to walk very far away, then wait for a while, then try and enter again.
Me
same as last poster.
No notification.
Robert
Works great on simulator but not on my iPhone 4 iOS 7.1
David
Hi, Nice tutorial. I have gone through quite of few tutorials on geofencing, but none seem to mention how to watch and register regions in the users immediate vicinity including Apple.
A good example will be a speed cameras app. Let’s say you have a database of 100 speed cameras and you are only allowed to monitor twenty cameras at one time. How do you know which cameras to load as you approach them? I am assuming that, you would have to implement a pretty sophisticated algorithm to search the data correct?
Thanks
David
samkeeneinteractivedesign@gmail.com
Hi David, this is where it gets tricky, although not impossible. You need to have a list/JSON file of all the regions you wish to monitor and then listen for the significantUpdateInLocation delegate method, then load in the closest 20 regions and start monitoring for them. So you’re dynamically loading and unloading the closest 20 regions based on the users current location.
Robert
Hi Sam.
Great tutorial.
I have this working on my iPhone 4 now.
What would be the best way to fire a different notification message for each location? Currently all fences launch “You’ve entered a geofence.”
Thank you.
samkeeneinteractivedesign@gmail.com
Good question, you’ll need to check your region against a white list of regions you are monitoring for and then change the notification accordingly
Robert
… and along comes iOS 8 and everything breaks.
Hi Sam. I had this working perfectly, but with the new Xcode and iOS 8, things are broken.
Any chance you will update this tut?
Thank you
vishal adatia
Hi, Very good tut, i have question about while registering all geo location need network connectivity or just need the Location service enabled for registration ?
virneder
Great tutorial for new comer