在地理围栏中多次调用区域监控方法

Posted

技术标签:

【中文标题】在地理围栏中多次调用区域监控方法【英文标题】:Region Monitoring method getting called multiple times in Geo-Fencing 【发布时间】:2016-04-23 05:33:11 【问题描述】:

我创建了多个地理围栏来监控区域进入/退出事件。

我在AppDelegate.h 文件中创建了一个位置管理器

@interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>

@property (strong, nonatomic) UIWindow *window;

@property(nonatomic,retain)CLLocationManager *locationManager;
@property(nonatomic,retain)CLLocation *currentLocation;

+(AppDelegate *)sharedDelegate;

AppDelegate.m文件

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 

    UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];

    if (notification) 
        NSLog(@"AppDelegate didFinishLaunchingWithOptions");
        application.applicationIconBadgeNumber = 0;
    
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
    
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound) categories:nil];
        [application registerUserNotificationSettings:settings];
    
    else // ios 7 or earlier
    
        UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
        [application registerForRemoteNotificationTypes:myTypes];
    
    if (!self.locationManager)
    
        self.locationManager = [[CLLocationManager alloc] init];
    
    self.locationManager.delegate = self;
    //locationManager.distanceFilter = kCLDistanceFilterNone;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
    self.locationManager.distanceFilter = 2.0f;
    self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    
        [self.locationManager requestAlwaysAuthorization];
    

    if ([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)])
    
        self.locationManager.allowsBackgroundLocationUpdates  = YES;
    
    if ([self.locationManager respondsToSelector:@selector(pausesLocationUpdatesAutomatically)])
    
        self.locationManager.pausesLocationUpdatesAutomatically= NO;
    

    [self.locationManager stopMonitoringSignificantLocationChanges];

    if ([CLLocationManager locationServicesEnabled] && [CLLocationManager authorizationStatus] != kCLAuthorizationStatusDenied)
    
        [self.locationManager startUpdatingLocation];
    
        // Override point for customization after application launch.
    return YES;


-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region

    NSLog(@"Started monitoring %@ region",region.identifier);


-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations

    NSLog(@"%@",[locations description]);

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region

    dispatch_async(dispatch_get_main_queue(), ^
    if ([[UIApplication sharedApplication] applicationState]==UIApplicationStateBackground || [[UIApplication sharedApplication] applicationState]==UIApplicationStateInactive)
    
        UILocalNotification *localnotification = [[UILocalNotification alloc]init];
        localnotification.fireDate=[NSDate dateWithTimeIntervalSinceNow:1];
        localnotification.alertBody=@"You are enter in region.";
        localnotification.timeZone=[NSTimeZone defaultTimeZone];
        localnotification.repeatInterval = 0;
        localnotification.hasAction=YES;
        [[UIApplication sharedApplication]scheduleLocalNotification:localnotification];
    
    else
    
        [[[UIAlertView alloc]initWithTitle:@"message" message:@"Enter into region." delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok ", nil] show];
    
    );


-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region

     dispatch_async(dispatch_get_main_queue(), ^
    if ([[UIApplication sharedApplication] applicationState]==UIApplicationStateBackground || [[UIApplication sharedApplication] applicationState]==UIApplicationStateInactive)
    
        UILocalNotification *localnotificationExit = [[UILocalNotification alloc]init];
        localnotificationExit.fireDate=[NSDate dateWithTimeIntervalSinceNow:1];
        localnotificationExit.alertBody=@"You are exit from region.";
        NSLog(@"Exit from region.");
        localnotificationExit.timeZone=[NSTimeZone defaultTimeZone];
        localnotificationExit.repeatInterval = 0;
        localnotificationExit.hasAction=YES;
        [[UIApplication sharedApplication]scheduleLocalNotification:localnotificationExit];
    
    else
    
        [[[UIAlertView alloc]initWithTitle:@"message" message:@"Exit from region." delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok ", nil] show];
    
     );


- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error

    NSLog(@"didFailWithError: %@", error);
    [[[UIAlertView alloc] initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];

这个东西是管理区域监控的。

现在我的视图控制器正在添加要监控的区域。

-(void)AddRegionsInGeoFence

    NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];

    //----1
    CLLocationCoordinate2D centerCoordinate1 = CLLocationCoordinate2DMake(23.046518, 72.543337);
    CLCircularRegion *region1 =[[CLCircularRegion alloc] initWithCenter:centerCoordinate1 radius:200 identifier:@"Location First"];
    NSLog(@"%@",[region1 description]);
    region1.notifyOnEntry=YES;
    region1.notifyOnExit=YES;

    if (![standardDefaults boolForKey:@"EnterRegion"])
    
        [[AppDelegate sharedDelegate].locationManager startMonitoringForRegion:region1];
        NSLog(@"Started Monitoring- %@", [region1 description]);
    
    [self.mapview setShowsUserLocation:YES];
    [self.mapview setUserTrackingMode:MKUserTrackingModeFollow animated:YES];


    //----2
    CLLocationCoordinate2D centercoordinate2=CLLocationCoordinate2DMake(23.064381, 72.531181);
    CLCircularRegion *region2=[[CLCircularRegion alloc]initWithCenter:centercoordinate2 radius:200 identifier:@"Location Second"];
    NSLog(@"%@",[region2 description]);
    region2.notifyOnEntry=YES;
    region2.notifyOnExit=YES;

    if (![standardDefaults boolForKey:@"EnterRegion"])
    
        [[AppDelegate sharedDelegate].locationManager startMonitoringForRegion:region2];
        NSLog(@"Started Monitoring- %@", [region2 description]);
            

    //----3
    CLLocationCoordinate2D centercoordinate3=CLLocationCoordinate2DMake(23.083583,72.546441);
    CLCircularRegion *region3=[[CLCircularRegion alloc]initWithCenter:centercoordinate3 radius:200 identifier:@"Location Third"];
    NSLog(@"%@",[region3 description]);
    region3.notifyOnEntry=YES;
    region3.notifyOnExit=YES;
    if (![standardDefaults boolForKey:@"EnterRegion"])
    
        [[AppDelegate sharedDelegate].locationManager startMonitoringForRegion:region3];
        NSLog(@"Started Monitoring- %@", [region3 description]);
    


    //4
    CLLocationCoordinate2D centercoordinate4=CLLocationCoordinate2DMake(23.122255, 72.584499);
    CLCircularRegion *region4=[[CLCircularRegion alloc]initWithCenter:centercoordinate4 radius:500 identifier:@"Location Fourth"];
    NSLog(@"%@",[region4 description]);

    region4.notifyOnEntry=YES;
    region4.notifyOnExit=YES;

    if (![standardDefaults boolForKey:@"EnterRegion"])
    
        [[AppDelegate sharedDelegate].locationManager startMonitoringForRegion:region4];
        NSLog(@"Started Monitoring- %@", [region4 description]);
        [standardDefaults setBool:YES forKey:@"EnterRegion"];
        [standardDefaults synchronize];
    

我的问题是区域监控方法被多次调用,即使我没有进入区域本身。其他一切工作正常,Accuracy buffer50-80 meters 附近,这对我来说很好。

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region

此外,如果我关闭 Wi-Fi,那么它会背靠背调用这些方法,说退出区域并进入区域。据我所知,GPS 精度取决于 Wi-Fi。

任何帮助将不胜感激。

【问题讨论】:

我的代码中也有同样的问题。当我还在地理围栏中时,多次调用区域监控方法。这里是my code @Merry 是的,我已经浏览了此链接,但您的问题有所不同。我的代码被多次调用,你甚至没有被调用。 是的,你说得对,我的问题标题与不调用任何委托方法有关,但现在成功调用了 Enter 和 exit 方法,但是当用户已经在区域中时它会调用多次。它多次显示**进入或退出**通知。 【参考方案1】:

在修复苹果错误期间,可能的临时解决方法是限制回调的速率;因此不会作用于所有回调,而是限制回调可以被处理的速率。

在时间段到期之前发生的回调执行部分将被忽略。

以下是可以提供帮助的示例代码,未测试: 速率限制为 2 秒。

-(void)methodRateLimit 

    @synchronized(self) 
        // rate limit begin
        static NSDate *lastTimeExit = nil;

        if (!lastTimeExit) 
            lastTimeExit = [NSDate distantPast]; // way back in time
        

        NSDate *now = [NSDate date];
        if ([now timeIntervalSinceDate:lastTimeExit] > 2) 
            // do work here
            NSLog(@"Executing");
            lastTimeExit = now;
         else 
            NSLog(@"Limiting");
        
    

【讨论】:

以上是关于在地理围栏中多次调用区域监控方法的主要内容,如果未能解决你的问题,请参考以下文章

如何提高区域跨界精度(模拟)(地理围栏)

ibeacons 和地理围栏结合 swift

地理围栏和 iOS:检查我们是不是在一个区域内

地理围栏 PendingIntent 始终为空

didEnterRegion 和 didDetermineState 都调用了

如何更改地理围栏的形状