iOS应用程序使用地理围栏来通知用户有关预定义的附近位置的信息。允许应用程序错过某个位置(用户没有收到有关附近位置的通知),但是希望保持较低的丢失率。
实现这一目标的一种方法是使用startMonitoringSignificantLocationChanges
开始监控重要的变更位置,每次触发“位置变更”事件时,查找报告位置的半径500米内的位置。
让我担心的是,每次发生重大位置变化时都要求对附近区域进行查询,这会影响电池。
另一种方法是使用startMonitoringForRegion
注册位置,但Apple对同时跟踪的区域数量(合理)限制为20,而我们的位置显着超过20个。因此需要对跟踪区域进行某种动态更新,但我仍然不确定最佳方法是什么。
有关如何做到这一点的任何想法,以便保持较低的电池消耗,但也具有较低的位置丢失率?
答案 0 :(得分:21)
由于这个问题的活动不多,我将描述我们目前是如何解决这个问题的。
我们将新区域的重新加载与重要的位置变更(SLC)事件联系在一起。当SLC发生时,我们检查应该“地理围栏”的20个相邻区域。为了找到20个最接近的区域,我们根据以下公式简单地逼近纬度和经度的1':
纬度:1度= 110.54公里
经度:1度= 111.320 * cos(纬度)km
并检查设备当前位置的边界平方,以查看受监控区域的中心(参见:Simple calculations for working with lat/lon + km distance?)
因此,例如,如果(10N,10E)是设备的当前位置,我们从带有顶点的边界正方形开始(10-1',10-1'),(X-10',10 + 1'),(10 + 1',10 + 1'),(10 + 1',10-1')(在纬度(10N,10E),一个纬度/经度分钟接近1,85 km)。
如果有20个(或差不多20个) - 我们将它们注册为地理围栏并等待下一个SCL。如果更少/更多,只需增加/减少边界矩形的大小并重复搜索。
您可以调整此搜索算法以获得更好的性能,但此处描述的搜索算法已经完成了这项工作。
答案 1 :(得分:8)
您可以为“meta-geofence”保留一个位置,其中包含所有当前监控的位置。当用户离开此地理围栏时,将通知应用程序。然后,应用程序可以自行更新并停止跟踪最远的区域并开始跟踪附近的新区域。
答案 2 :(得分:5)
我想我会在您的应用中添加20个以上Geofences的选项。这种方式在我们的应用程序中已经运行了很长时间,并使用内置的CLLocation
方法。
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if (locations.count > 0) {
CLLocation *location = locations[0];
NSMutableArray *sortedFences = [[NSMutableArray alloc] init];
// add distance to each fence to be sorted
for (GeofenceObject *geofence in enabledFences) {
// create a CLLocation object from my custom object
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(geofence.latitude, geofence.longitude);
CLLocation *fenceLocation = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude];
// calculate distance from current location
CLLocationDistance distance = [location distanceFromLocation:fenceLocation];
// save distance so we can filter array later
geofence.distance = distance;
[sortedFences addObject:geofence];
}
// sort our array of geofences by distance and add we can add the first 20
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:@"distance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
NSArray *sortedArray = [sortedFences sortedArrayUsingDescriptors:sortDescriptors];
// should only use array of 20, but I was using hardcoded count to exit
for (GeofenceObject *geofence in sortedArray) {
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(geofence.latitude, geofence.longitude);
CLLocationDistance radius = geofence.radius;
NSString *ident = geofence.geofenceId;
CLCircularRegion *fenceRegion = [[CLCircularRegion alloc] initWithCenter:coordinate radius:radius identifier:ident];
fenceRegion.notifyOnEntry = geofence.entry;
fenceRegion.notifyOnExit = geofence.exit;
[locationController.locationManager startMonitoringForRegion:fenceRegion];
}
}
}
希望这可以帮助某人或引导他们走上正确的道路。
答案 3 :(得分:3)
如果您担心对每个重要位置更改执行接近检查,您可以使用R-trees或R*-tree等空间索引/搜索方法来减少每个位置更改所需的比较次数,因为那些搜索算法将过滤掉(可能很大的)空间无关区域。这应该减少执行接近检查所需的时间/电池电量。
答案 4 :(得分:1)
我知道这篇文章很老,但对于那些希望做类似事情的人来说,Skyhook提供了对无数场地进行地理围栏的能力。
从他们的营销: Skyhook的Context Accelerator使应用程序开发人员和广告商能够通过简单的Web界面将Infinite Geofences即时部署到任何品牌链(如CVS)或场地类别(如便利店)。使用Skyhook第一方位置网络中的相同专利技术,Context Accelerator SDK可管理设备上的这些活动地理围栏,无论操作系统限制是否允许无限地理围栏。