CLLocationManager位置监视无法正常工作

时间:2016-01-28 13:31:27

标签: ios objective-c iphone cocoa-touch cllocationmanager

我有一个应用程序,每当他接近我的一个客户的商店时都会通知用户。有超过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.
}
你能帮帮我吗?谢谢!

1 个答案:

答案 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个商店

我以前的回答是针对第一个问题。 关于第二个问题,动态重新计算最接近的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。