问题
Hi Guys Am working on Geo-Fencing! Location manager didDetermineState is calling properly but when i entered region didEnterRegion and didExitRegion never been invoked.
Here my code is
**ViewController.m**
GeofenceMonitor * gfm = [GeofenceMonitor sharedObj];
NSMutableDictionary * fence1 = [NSMutableDictionary new];
[fence1 setValue:@"office" forKey:@"identifier"];
[fence1 setValue:@"13.04765701" forKey:@"latitude"];
[fence1 setValue:@"80.18752289" forKey:@"longitude"];
[fence1 setValue:@"100" forKey:@"radius"];
[fence1 setValue:@"11" forKey:@"id"];
NSMutableDictionary * fence2 = [NSMutableDictionary new];
[fence2 setValue:@"axis baank end" forKey:@"identifier"];
[fence2 setValue:@"13.04705048" forKey:@"latitude"];
[fence2 setValue:@"80.18778229" forKey:@"longitude"];
[fence2 setValue:@"100" forKey:@"radius"];
[fence2 setValue:@"12" forKey:@"id"];
if([gfm checkLocationManager])
{
[gfm addGeofence:fence1];
[gfm addGeofence:fence2];
[gfm findCurrentFence];
}
GeofenceMonitor.m
-(id) init
{
self = [super init];
if(self)
{
arr_region=[[NSMutableArray alloc] init];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
[locationManager startUpdatingLocation];
}
return self;
}
+(GeofenceMonitor *) sharedObj
{
static GeofenceMonitor * shared =nil;
static dispatch_once_t onceTocken;
dispatch_once(&onceTocken, ^{
shared = [[GeofenceMonitor alloc] init];
});
return shared;
}
- (CLRegion*)dictToRegion:(NSDictionary*)dictionary
{
NSString *identifier = [dictionary valueForKey:@"id"];
CLLocationDegrees latitude = [[dictionary valueForKey:@"latitude"] doubleValue];
CLLocationDegrees longitude =[[dictionary valueForKey:@"longitude"] doubleValue];
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude);
CLLocationDistance regionRadius = [[dictionary valueForKey:@"radius"] doubleValue];
if(regionRadius > locationManager.maximumRegionMonitoringDistance)
{
regionRadius = locationManager.maximumRegionMonitoringDistance;
}
NSString *version = [[UIDevice currentDevice] systemVersion];
CLRegion * region =nil;
if([version floatValue] >= 7.0f) //for iOS7
{
region = [[CLCircularRegion alloc] initWithCenter:centerCoordinate
radius:regionRadius
identifier:identifier];
}
else // iOS 7 below
{
region = [[CLRegion alloc] initCircularRegionWithCenter:centerCoordinate
radius:regionRadius
identifier:identifier];
}
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
NSLog(@"region is %@", region);
return region;
}
- (void) initializeRegionMonitoring:(NSArray*)geofences {
if(![CLLocationManager regionMonitoringAvailable]) {
return;
}
for(CLRegion *geofence in geofences) {
[locationManager startMonitoringForRegion:geofence];
}
}
-(BOOL) checkLocationManager
{
if(![CLLocationManager locationServicesEnabled])
{
[self showMessage:@"You need to enable Location Services"];
return FALSE;
}
if(![CLLocationManager isMonitoringAvailableForClass:[CLRegion class]])
{
[self showMessage:@"Region monitoring is not available for this Class"];
return FALSE;
}
if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied ||
[CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted )
{
[self showMessage:@"You need to authorize Location Services for the APP"];
return FALSE;
}
return TRUE;
}
-(void) addGeofence:(NSDictionary*) dict
{
CLRegion * region = [self dictToRegion:dict];
[arr_region addObject:[self dictToRegion:dict]];
[self initializeRegionMonitoring:arr_region];
[locationManager startMonitoringForRegion:region];
}
-(void) findCurrentFence
{
NSString *version = [[UIDevice currentDevice] systemVersion];
if([version floatValue] >= 7.0f) //for iOS7
{
NSArray * monitoredRegions = [locationManager.monitoredRegions allObjects];
for(CLRegion *region in monitoredRegions)
{
[locationManager requestStateForRegion:region];
}
}
else
{
[locationManager startUpdatingLocation];
}
}
-(void) removeGeofence:(NSDictionary*) dict
{
CLRegion * region = [self dictToRegion:dict];
[locationManager stopMonitoringForRegion:region];
}
-(void) clearGeofences
{
NSArray * monitoredRegions = [locationManager.monitoredRegions allObjects];
for(CLRegion *region in monitoredRegions) {
[locationManager stopMonitoringForRegion:region];
}
}
/*
Delegate Methods
*/
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
if(state == CLRegionStateInside)
{
NSLog(@"##Entered Region - %@", region.identifier);
}
else if(state == CLRegionStateOutside)
{
NSLog(@"##Exited Region - %@", region.identifier);
}
else{
NSLog(@"##Unknown state Region - %@", region.identifier);
}
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion: (CLRegion *)region
{
NSLog(@"Started monitoring %@ region", region.identifier);
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{ NSLog(@"Entered Region - %@", region.identifier);
UILocalNotification *notification = [[UILocalNotification alloc]init];
[notification setAlertBody:[NSString stringWithFormat:@"Welcome you have entered geo-fence area"]];
[notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
[notification setTimeZone:[NSTimeZone defaultTimeZone]];
[[UIApplication sharedApplication] setScheduledLocalNotifications:[NSArray arrayWithObject:notification]];
NSLog(@"Notification is %@",notification);
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{ NSLog(@"Exited Region - %@", region.identifier);
UILocalNotification *notification = [[UILocalNotification alloc]init];
[notification setAlertBody:[NSString stringWithFormat:@"Welcome you have entered geo-fence area"]];
[notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
[notification setTimeZone:[NSTimeZone defaultTimeZone]];
[[UIApplication sharedApplication] setScheduledLocalNotifications:[NSArray arrayWithObject:notification]];
NSLog(@"Notification is %@",notification);
}
- (void) locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
NSSet * monitoredRegions = locationManager.monitoredRegions;
[self locateCurrentGeofenceWithLocation:[locations lastObject] InMonitoredRegions:monitoredRegions];
[locationManager stopUpdatingLocation];
}
- (void) locateCurrentGeofenceWithLocation:(CLLocation *)newLocation
InMonitoredRegions:(NSSet *) monitoredRegions
{
NSString *version = [[UIDevice currentDevice] systemVersion];
// if([version floatValue] < 7.0f) // below iOS7
// {
[monitoredRegions enumerateObjectsUsingBlock:^(CLRegion *region,BOOL *stop)
{
NSString *identifer = region.identifier;
NSLog(@"regions are %@",identifer);
CLLocationCoordinate2D centerCoords =region.center;
CLLocationCoordinate2D currentCoords= CLLocationCoordinate2DMake(newLocation.coordinate.latitude,newLocation.coordinate.longitude);
CLLocationDistance radius = region.radius;
NSNumber * currentLocationDistance =[self calculateDistanceInMetersBetweenCoord:currentCoords coord:centerCoords];
if([currentLocationDistance floatValue] < radius)
{
NSLog(@"Invoking didEnterRegion Manually for region: %@",identifer);
//stop Monitoring Region temporarily
[locationManager stopMonitoringForRegion:region];
[self locationManager:locationManager didDetermineState:CLRegionStateInside forRegion:region];
//start Monitoing Region
[locationManager startMonitoringForRegion:region];
}
// }];
}];
}
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
NSLog(@"monitoringDidFailForRegion %@ %@",
region, error.localizedDescription);
for (CLRegion *monitoredRegion in manager.monitoredRegions) {
NSLog(@"monitoredRegion: %@", monitoredRegion);
}
if ((error.domain != kCLErrorDomain || error.code != 5) &&
[manager.monitoredRegions containsObject:region]) {
NSString *message = [NSString stringWithFormat:@"%@ %@",
region, error.localizedDescription];
UIAlertView *notificationAlert = [[UIAlertView alloc] initWithTitle:@"monitoringDidFailForRegion"
message:message
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles: nil];
[notificationAlert show];
}
}
回答1:
Please try to call on main thread.
if ([CLLocationManager locationServicesEnabled])
{
[self performSelectorOnMainThread:@selector(updateLocation) withObject:self waitUntilDone:NO];
}
- (void)updateLocation
{
arr_region=[[NSMutableArray alloc] init];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
[locationManager startUpdatingLocation];
}
i hope it helpful.
来源:https://stackoverflow.com/questions/25178981/geo-fencing-didenterregion-and-didexitregion-methods-not-called