iOS Geofence,监控启动时如何处理内部区域? [英] iOS Geofence, how to handle when inside region when monitoring starts?

查看:250
本文介绍了iOS Geofence,监控启动时如何处理内部区域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当调用 startMonitoringForRegion 时,我一直无法解决如何处理手机已经在某个区域内的情况?其他问题建议在 didStartMonitoringForRegion 中调用 requestStateForRegion 然后调用方法 didDetermineState:forRegion:。所以代码看起来像这样:

I have been unable to work out how to handle a scenario where the phone is already inside a region when startMonitoringForRegion is called? Other questions have suggested calling requestStateForRegion inside didStartMonitoringForRegion this then calls the method didDetermineState: forRegion:. So the code looks something like this:

- (void)viewDidLoad {
    //location manager set up etc...
    for (Object *object in allObjects){

        CLRegion *region = [self geofenceRegion:object];
        [locationManager startMonitoringForRegion:region];
     }
}

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

    [self.locationManager requestStateForRegion:region];
    [self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
 }

- (void)locationManager:(CLLocationManager *)manager
  didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {

    if (state == CLRegionStateInside){
        [self locationManager:locationManager didEnterRegion:region];
    }  
}

现在显然geofenceRegion方法是我自己的,它的工作原理很好,对象包含像lat long和radius这样的东西,所有这些都很好,所以这不是问题。

Now obviously the method geofenceRegion is my own and it works fine, and the objects contains things like lat long and radius and that all works fine as well so that is not the problem here.

无论如何,上面代码的问题如果用户在将区域添加到其设备时已经在区域内(即完成了didEnterRegion),它确实有效。但问题是每次按照苹果文档划分其中一个边界区域时,也会调用方法 didDetermineState:forRegion:

Anyway, the problem with the above code is that it does work if the user is already inside the region when it adds the region to their device (ie. didEnterRegion is done). However the problem is that the method didDetermineState: forRegion: is also called every time one of the boundary regions is crossed as per the apple docs:


只要存在区域的边界转换,位置管理器就会调用此方法。除了调用locationManager:didEnterRegion:和locationManager:didExitRegion:methods之外,它还调用此方法。位置管理器还调用此方法以响应对其requestStateForRegion:方法的调用,该方法以异步方式运行。

The location manager calls this method whenever there is a boundary transition for a region. It calls this method in addition to calling the locationManager:didEnterRegion: and locationManager:didExitRegion: methods. The location manager also calls this method in response to a call to its requestStateForRegion: method, which runs asynchronously.

现在因为这一切输入一个区域的时间, didEnterRegion 会被自动调用,但之后会再次调用它,因为 didDetermineState:forRegion:也会自动调用根据apple docs调用,这会导致再次调用 didEnterRegion ,因此当我只想输入一次时,区域会输入两次。我该如何避免这种情况?

Now because of this every time a region is entered, didEnterRegion is automatically called but then it is called again because didDetermineState: forRegion: is also automatically called as per the apple docs and this results in didEnterRegion being called again so the region is entered twice when i only want it to be entered once. How can i avoid this?

感谢您的帮助。

解决方案

解决方案真的很简单我只是走错路。我必须选择使用2种方法 didEnterRegion: didExitRegion 或使用 didDetermineState: forRegion 并创建我自己的进入和退出区域的方法,两者都不应该使用

The solution really is so simple i was just going about it the wrong way. I had to choose to either use the 2 methods didEnterRegion: and didExitRegion or use didDetermineState: forRegion and create my own methods for entering and exiting the region, both should not be used.

所以我选择只使用 didDetermineState:forRegion 方法,我的代码现在看起来像这样:

So i have chosen to use only the didDetermineState: forRegion method and my code now looks like this:

请注意,使用此方法,如果不在内部,将为区域调用退出区域,如果像我一样,您只想在输入发生后退出您将需要某种方法来检查区域是否已经输入(我自己使用核心数据,因为我已经使用它来存储区域的其他方面)。

- (void)viewDidLoad {
    //location manager set up etc...
    for (Object *object in allObjects){

        CLRegion *region = [self geofenceRegion:object];
        [locationManager startMonitoringForRegion:region];
     }
}

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

    [self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
}

- (void)locationManager:(CLLocationManager *)manager
  didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {

    if (state == CLRegionStateInside){

        [self enterGeofence:region];

    } else if (state == CLRegionStateOutside){

        [self exitGeofence:region];

    } else if (state == CLRegionStateUnknown){
        NSLog(@"Unknown state for geofence: %@", region);
        return;
    }
}

- (void)enterGeofence:(CLRegion *)geofence {

    //whatever is required when entered
}

- (void)exitGeofence:(CLRegion *)geofence {

    //whatever is required when exit
}


推荐答案

只是不要使用 locationManager:didEnterRegion:,因为 locationManager:didDetermineState:forRegion:为您提供触发入门代码所需的所有信息,顺便说一句,它不应该是 locationManager:didEnterRegion:,使用您的自己的选择器,它不是 CLLocationManagerDelegate 协议的一部分。

Just do not use locationManager:didEnterRegion: at all, as locationManager:didDetermineState:forRegion: gives you all the info you need to trigger the on-entry code, which, by the way, should not be the locationManager:didEnterRegion:, use your own selector, which is not a part of CLLocationManagerDelegate protocol.

另一种方法是在开始监控区域时测试区域内的位置。这个解决方案听起来并不是那么简单:你需要先调用 startUpdatingLocation 来更新当前位置,因为只需读取locationManager的location属性就可能会让你过时或极不准确。

Another approach is to test for inside a region location when starting to monitor a region. This solution is not that trivial as it sounds though: you need to update current location first by calling startUpdatingLocation, as just reading location property of locationManager will probably give you stale or extremely inaccurate reading.

这篇关于iOS Geofence,监控启动时如何处理内部区域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆