一、簡介
開發(fā)時遇到一個需求,快到家時App提醒用戶,做相應的操作。經(jīng)研究,發(fā)現(xiàn)OC的電子圍欄技術能夠滿足自己的需求,于是寫了一個 Demo,做個記錄,也和大家分享一下。
區(qū)域監(jiān)測,也稱地理圍欄,或者臨近警告。如果希望iOS設備進出某個區(qū)域發(fā)出通知,那么這種區(qū)域監(jiān)測的功能也被稱為臨近警告。此功能實現(xiàn)的是:首先創(chuàng)建一個區(qū)域(圍欄),當用戶設備進入或者離開此區(qū)域時,會有相應的代理方法響應,開發(fā)者可以做一些操作。并且最重要的一點是當開啟了區(qū)域監(jiān)控,即使用戶殺死了APP還是可以監(jiān)聽到代理方法的響應,從而做一些操作。

區(qū)域監(jiān)測我們3種方法完成,第一種是OC自有的,利用CLLocationManager監(jiān)測若干CLCircularRegion區(qū)域,第二種是集高德地圖的功能,第三種是集成百度地圖的功能。本文主要介紹OC自有的功能,介紹原理使用。
二、具體實現(xiàn)
1、開啟后臺定位功能

2、配置Info.plist描述文件
Privacy - Location Always and When In Use Usage Description
Privacy - Location Always Usage Description
Privacy - Location When In Use Usage Description

3、初始化CLLocationManager
創(chuàng)建CLLocationManager對象,該對象負責獲取定位相關信息,并為該對象設置一些必要的屬性。
- (CLLocationManager *)locationMgr {
if (!_locationMgr) {
_locationMgr = [[CLLocationManager alloc] init];
_locationMgr.delegate = self;
_locationMgr.desiredAccuracy = kCLLocationAccuracyBest;
_locationMgr.distanceFilter = 10;
// 主動請求定位授權(quán)
[_locationMgr requestAlwaysAuthorization];
// 這是iOS9中針對后臺定位推出的新屬性 不設置的話 可是會出現(xiàn)頂部藍條的哦(類似熱點連接)
[_locationMgr setAllowsBackgroundLocationUpdates:YES];
_locationMgr.pausesLocationUpdatesAutomatically = NO;
}
return _locationMgr;
}
4、設置監(jiān)聽的位置
設置需要監(jiān)聽的地址位置,及監(jiān)聽的圓形區(qū)域,包括中心點幾半徑,可設置多個區(qū)域。
// 設置監(jiān)聽的位置
- (void)regionObserveWithLocation:(CLLocationCoordinate2D)location {
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"您的設備不支持定位");
return;
}
// 設置區(qū)域半徑
CLLocationDistance radius = 200;
// 使用前必須判定當前的監(jiān)聽區(qū)域半徑是否大于最大可被監(jiān)聽的區(qū)域半徑
if(radius > self.locationMgr.maximumRegionMonitoringDistance) {
radius = self.locationMgr.maximumRegionMonitoringDistance;
}
// 設置id
NSString *identifier =
[NSString stringWithFormat:@"%f , %f", location.latitude, location.longitude];
// 使用CLCircularRegion創(chuàng)建一個圓形區(qū)域,
CLRegion *fkit = [[CLCircularRegion alloc] initWithCenter:location
radius:radius
identifier:identifier];
// 開始監(jiān)聽fkit區(qū)域
[self.locationMgr startMonitoringForRegion:fkit];
// 請求區(qū)域狀態(tài)(如果發(fā)生了進入或者離開區(qū)域的動作也會調(diào)用對應的代理方法)
[self.locationMgr requestStateForRegion:fkit];
}
5、實現(xiàn)代理方法
當?shù)刂肺恢酶淖儠r,會代理方法的回調(diào),包括進入?yún)^(qū)域、離開區(qū)域,及錯誤回調(diào)。CLLocationManagerDelegate 還有其他代理方法,這里就不多做介紹。
// 進入指定區(qū)域以后將彈出提示框提示用戶
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSString *msg = [NSString stringWithFormat:@"進入指定區(qū)域 %@", region.identifier];
[self dealAlertWithStr:msg];
}
// 離開指定區(qū)域以后將彈出提示框提示用戶
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSString *msg = [NSString stringWithFormat:@"離開指定區(qū)域 %@", region.identifier];
[self dealAlertWithStr:msg];
}
// 監(jiān)聽區(qū)域失敗時調(diào)用
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error {
NSLog(@"監(jiān)聽區(qū)域失敗 : %@", error);
}
6、開啟監(jiān)聽
開啟監(jiān)聽的方法,我放在的App啟動的時候,為了能讓程序被殺掉時也能觸發(fā)通知。當用戶設置始終訪問地理位置權(quán)限時,即使App被殺死,當用戶位置改變,進入或離開監(jiān)控區(qū)域時都會喚醒App,會走 didFinishLaunchingWithOptions 方法。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self registerNotifaction];
[self awakeForRegionWithOptions:launchOptions];
return YES;
}
// APP被喚醒機制
- (void)awakeForRegionWithOptions:(NSDictionary *)launchOptions {
// 應用啟動時開啟監(jiān)聽
[[ZJHRegionManager shareInstance] starMonitorRegion];
// 被區(qū)域監(jiān)測喚醒
// 我在模擬器測試,更改地理位置時,launchOptions數(shù)據(jù)為空
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
NSLog(@"區(qū)域監(jiān)測喚醒");
}
}
三、測試驗證
1、前臺測試
可通過修改模擬的地址位置,測試位置變更


2、后臺測試
想要殺掉App也能監(jiān)控區(qū)域,要設置一下定位服務,選擇“始終”。這里有個問題,就是殺掉app后,監(jiān)聽位置變更后,收到了兩條推送。暫時還沒定位到問題,知道原因的朋友,歡迎評論留言,多多指教。


3、可能會遇到的問題
- 與其他App中地理位置設置有沖突,導致設置位置失敗。
- 與集成的百度地圖或高德地圖監(jiān)控位置有沖突。
遇到問題不要慌,仔細排查,總是能解決的。祝君好運!??????
參考鏈接:
Demo 下載
iOS地理圍欄技術的應用
iOS區(qū)域監(jiān)控(地理圍欄)
iOS開發(fā)-電子圍欄區(qū)域監(jiān)聽深入篇