2016-01-28 3 views
0

У меня есть приложение, которое будет уведомлять пользователя каждый раз, когда он подходит к одному из магазинов моего клиента. Есть более 20 магазинов, поэтому у меня есть функция, которая берет местоположение пользователя и находит для него 20 ближайших магазинов и начинает отслеживать местоположение этих магазинов, каждый раз, когда пользователь перемещается, приложение снова находит 20 ближайших магазинов, удаляет предыдущие магазины отслеживают и запускают мониторинг новых.Мониторинг местоположения CLLocationManager не работает должным образом

По какой-то причине это не сработает, я буду рад, если один из вас (или больше :)) поможет мне найти проблему, спасибо!

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

что не работает? CLLocationManager или ваша идентификация ближайшего магазина? – CharlesThierry

+0

@CharlesThierry Когда пользователь подходит к региону 'locationManager: didEnterRegion:' не вызывается. –

+0

Что-то подобное случилось со мной, когда я попытался настроить CLLocationManager на фоновый поток. Может быть, попробуйте позвонить вам код из основного потока? – CharlesThierry

ответ

1

Я довольно новичок в CoreLocation, но я бы подумал, что не стоит называть stopMonitoringForRegions и startMonitoringForRegions в didUpdateLocations.

Поскольку вы контролируете регионы, делегат didEnterRegion - это то, что вас заинтересует. Это даст вам «эй, я пришел в событие X store», и там вы, вероятно, захотите позвонить код, который вы сейчас используете в своих файлах doUpdateLocations.

Вы хотите настройки CoreLocation, вероятно, в вашем AppDelegate, так что вы можете иметь что-то вроде (извините про то, что 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, код в вашем файле didUpdateLocations не будет вызываться, если вы не сообщите диспетчеру местоположения startUpdatingLocation. Только от верхней части моей головы:

// 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 никогда не вызывался.

+0

Я установил 'CLLocationManager' в' AppDelegate', как вы, я не думаю, что мне нужно использовать значительный мониторинг местоположения, потому что мне нужна информация о местоположении пользователя сразу и не каждые 15 минут (даже в документации Apple API упоминалось, что вы не должны использовать его для мониторинга региона). Но даже с 'didUpdateLocations' он не работает, есть ли у вас какие-либо идеи, почему? –

Смежные вопросы