我有一个应用程序,每当他接近我的一个客户的商店时都会通知用户。有超过20家商店,所以我有一个功能,它占用了用户的位置,并找到了他最近的20个商店,并开始监控这些商店的位置,每次用户移动,应用程序找到最近的20个商店再次存储,从监视中删除以前的存储并开始监视新存储。
出于某种原因,它不起作用,如果你们中的一个(或更多:)会帮助我找到问题,我会很高兴,谢谢!
myCode (滚动查看完整代码):
注意:CLLocationManager
及其代理人创建的AppDelegate.m
是此类(UIViewController
)。
-(void)sortClosestStores
{
[self.allStores sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
CLLocation *location1=[[CLLocation alloc] initWithLatitude:((Store*)obj1).geoPoint.latitude longitude:((Store*)obj1).geoPoint.longitude];
CLLocation *location2=[[CLLocation alloc] initWithLatitude:((Store*)obj2).geoPoint.latitude longitude:((Store*)obj2).geoPoint.longitude];
float dist1 =[location1 distanceFromLocation:self.locationManager.location];
float dist2 = [location2 distanceFromLocation:self.locationManager.location];
if (dist1 == dist2) {
return NSOrderedSame;
}
else if (dist1 < dist2) {
return NSOrderedAscending;
}
else {
return NSOrderedDescending;
}
}];
if (self.twentyClosestStores==nil) {
self.twentyClosestStores=[NSMutableArray array];
}
if (self.previousTwentyStores==nil) {
self.previousTwentyStores=[NSMutableArray array];
}
self.previousTwentyStores=self.twentyClosestStores;
self.twentyClosestStores=[NSMutableArray array];
for (int i = 0; i < 20; i++) {
[self.twentyClosestStores addObject:[self.allStores objectAtIndex:i]];
}
}
-(void)startMonitoringClosestStores
{
if (![CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
NSLog(@"Monitoring is not available for CLCircularRegion class");
}
for (Store *currentStore in self.twentyClosestStores) {
CLCircularRegion *region=[currentStore createCircularRegion];
[self.locationManager startMonitoringForRegion:region];
}
}
-(void)stopMonitoringStores
{
for (Store *currentStore in self.previousTwentyStores) {
CLCircularRegion *region=[currentStore createCircularRegion];
[self.locationManager stopMonitoringForRegion:region];
}
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
if (self.allStores!=nil) {
[self sortClosestStores];
[self stopMonitoringStores];
[self startMonitoringClosestStores];
}
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(@"Entered"); //Not called even when the user enters one of the regions.
}
你能帮帮我吗?谢谢!
答案 0 :(得分:1)
我自己在CoreLocation上很新,但我认为在didUpdateLocations中调用stopMonitoringForRegions和startMonitoringForRegions不是一个好主意。
由于您正在监视区域,因此您将感兴趣的是didEnterRegion委托。这将为您提供“嘿,我到达X商店”活动,并且在那里您可能想要调用您目前在didUpdateLocations中拥有的代码。
你可能想在你的AppDelegate中设置CoreLocation,所以你可能有类似的东西(抱歉它是Swift,这就是我现在正在做的事情):
locationManager.delegate = self
// auths:
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
// config:
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = true
locationManager.allowsBackgroundLocationUpdates = true
locationManager.activityType = CLActivityType.AutomotiveNavigation
// start:
locationManager.startMonitoringSignificantLocationChanges()
然后你会得到你的代码:
if (self.allStores!=nil) {
[self sortClosestStores];
[self stopMonitoringStores];
[self startMonitoringClosestStores];
}
注意:如果您在添加受监控区域之前或之后调用startMonitoringSignificantLocationChanges,我认为这并不重要,我的代码还没有那么远。
didUpdateLocations更适用于您想要跟踪位置的情况,例如跟踪骑自行车或慢跑。
补充说明: 好的,我想我现在明白了这个问题。您想要完成的任务有两个方面:
我以前的回答是针对第一个问题。 关于第二个问题,动态重新计算最接近的N,除非您告诉位置管理器startUpdatingLocation,否则不会调用didUpdateLocations中的代码。就在我的头顶:
// configure the location manager in AppDelegate:
// You will need to experiment with these two properties,
// you probably don't want to use kCLLocationAccuracyBestForNavigation.
// Maybe kCLLocationAccuracyKilometer would be sufficient.
locmgr.distanceFilter = n
locmgr.desiredAccuracy = m
locmgr.pausesLocationUpdatesAutomatically = true
locmgr.startUpdatingLocation()
// this is the delegate that will receive the events due to locmgr.startUpdatingLocation
locationManager:didUpdateLocation {
// Unless you have a specific need for it, I would refactor so that
// you don't need self.PreviousTwentyStores:
[self stopMonitoringStores];
[self sortClosestStores];
[self startMonitoringClosestStores];
}
locationManager:didEnterRegion {
// you are in the region surrounding one of the stores.
}
或者,考虑设置一个计时器并每N秒或几分钟唤醒应用程序以重新计算最近的商店。
据我了解CoreLocation的各个方面
startUpdatingLocation - &gt; didUpdateLocations - &gt; stopUpdatingLocation
(在某种意义上)完全独立于:
startMonitoringForRegion - &gt; didEnterRegion | didExitRegion - &gt; stopMonitoringForRegion
此外,从未调用startUpdatingLocation,因此从未调用过didUpdateLocation。