【问题标题】:CLLocationManager location monitoring not working properlyCLLocationManager 位置监控无法正常工作
【发布时间】:2016-05-05 21:54:19
【问题描述】:

我有一个应用程序,它会在用户每次接近我客户的一家商店时通知用户。有20多家商店,所以我有一个功能,可以获取用户的位置并找到离他最近的20家商店并开始监控这些商店的位置,每次用户移动时,应用程序都会再次找到最近的20家商店,删除从监控以前的商店开始监控新的商店。

由于某种原因,它不起作用,如果你们中的一个(或更多:))能帮助我找到问题,我会很高兴,谢谢!!

myCode(滚动查看完整代码):

注意:CLLocationManagerAppDelegate.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.
}

你能帮帮我吗?谢谢!

【问题讨论】:

  • 什么不起作用? CLLocationManager,还是您最近的商店的标识?
  • @CharlesThierry 当用户接近一个未被调用的区域locationManager: didEnterRegion:
  • 当我尝试在后台线程上设置 CLLocationManager 时,发生了类似的事情。也许尝试从主线程调用你的代码?
  • @CharlesThierry 它在主线程上

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


【解决方案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 -> didUpdateLocations -> stopUpdatingLocation

(在某种意义上)完全独立于:

startMonitoringForRegion -> didEnterRegion | didExitRegion -> stopMonitoringForRegion

此外,从未调用过 startUpdatingLocation,因此从未调用过您的 didUpdateLocation。

【讨论】:

  • 我已经像你一样在AppDelegate 中设置了CLLocationManager,我认为我不需要使用重要的位置监控,因为我需要关于用户位置的信息,而不是每 15 分钟一次(即使在 Apple API 文档中也提到您不应该将其用于区域监控)。但即使使用didUpdateLocations 也不起作用,你知道为什么吗?
猜你喜欢
  • 1970-01-01
  • 2013-09-07
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多