didEnterRegion在前台工作,但不在后台或其他VC工作 [英] didEnterRegion works in foreground but not background or other VCs

查看:166
本文介绍了didEnterRegion在前台工作,但不在后台或其他VC工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果应用程序正在运行且CLLocationManagerDelegate类是前台(即可见),那么didEnterRegions会触发,我同时获得NSLog和AlertView。但是,当应用程序处于后台时,或者,如果屏幕显示除委托类之外的任何内容,我什么也得不到。

If the app is running and the CLLocationManagerDelegate class is the foreground (i.e. visible) then the didEnterRegions triggers and I get both the NSLog as well as the AlertView. However, I get nothing when the app is in the background or, essentially, if the screen is showing anything but the delegate class.

我已经设置了应用寄存器的位置在plist中更新在必需的背景模式下虽然我不确定是否有必要。

I have set "App registers for location updates" under "Required background modes" in the plist although I'm not sure that's even necessary.

这是我认为的相关代码,尽管我可能错了(并乐意添加更多)。我应该注意viewDidLoad中的所有内容都包含在if中,检查区域监视是否可用并启用。

Here's what I think is the relevant code although I may be wrong (and will gladly add more). I should note that everything in viewDidLoad is wrapped in an if which checks if region monitoring is available and enabled.

- (void)viewDidLoad
{
    NSLog(@"MapViewController - viewDidLoad");
    self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
    self.locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters;    
    self.locationManager.delegate = self;
    [self.locationManager startMonitoringSignificantLocationChanges];
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    NSLog(@"MapViewController - didEnterRegion");
    NSLog(@"MVC - didEnterRegion - region.radius = %f", region.radius);
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"entered region..." message:@"You have Entered the Location." delegate:nil cancelButtonTitle:@"OK"  otherButtonTitles: nil];
    alert.tag = 2;
    [alert show];
}

这里是我在AppDelegate.m中获取受监控区域列表的地方:

here is where I get the list of regions being monitored, in AppDelegate.m:

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

// other code

NSLog(@"LISTING ALL REGIONS MONITORED");
    NSArray *regions = [self.locationManager.monitoredRegions allObjects];
    if (!regions) {
        NSLog(@"no regions found");
    } else {
        NSLog(@"got %d monitored regions", [regions count]);
        for (int i = 0; i < [regions count]; i++) {
            CLRegion *region = [regions objectAtIndex:i];
            NSLog(@"region %d's identifier = %@", i, region.identifier);
            NSLog(@"region: radius: %@", region.radius);
        }
    }

// other code
}

我调用startMonitoringForRegion两次,这里是主要的地方:

I call startMonitoringForRegion twice, here's the main place:

- (void)doneButtonTapped {
    NSLog(@"doneButtonTapped");

    if (self.locationIdentifier) {
        if ([CLLocationManager regionMonitoringEnabled] && [CLLocationManager regionMonitoringAvailable]) {

            // core data setup
            NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
            NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"LocationReminder" inManagedObjectContext:self.managedObjectContext];
            fetchRequest.entity = entityDescription;
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"locationIdentifier == %@", self.locationIdentifier];
            fetchRequest.predicate = predicate;
            NSError *error;
            NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
            if (results) {

                // get the LocationReminder
                LocationReminder *retrievedReminder = [results objectAtIndex:0];
                retrievedReminder.audioURI = [[[self.audioPlayers objectAtIndex:self.selectedCell] url] absoluteString];
                retrievedReminder.userRecording = nil;

                // start monitoring it's region
                NSArray *coordinateArray = [retrievedReminder.locationIdentifier componentsSeparatedByString:@", "];
                CLLocationCoordinate2D coordinate = {[[coordinateArray objectAtIndex:0] doubleValue], [[coordinateArray objectAtIndex:1] doubleValue]};
                CLRegion *newRegion = [[CLRegion alloc] initCircularRegionWithCenter:coordinate radius:250.0 identifier:retrievedReminder.locationIdentifier];
                NSLog(@"about to monitor region with radius: %f", newRegion.radius);
                [self.locationManager startMonitoringForRegion:newRegion desiredAccuracy:kCLLocationAccuracyBest];

                // save the LocationReminder
                if (![self.managedObjectContext save:&error]) {
                    NSLog(@"hmm.  no managed object context.  must be something space-time going on");
                } else {
                    NSLog(@"saved locationReminder, locationIdentifier = %@", retrievedReminder.locationIdentifier);
                }
            } else {
                NSLog(@"ERROR: no LocationReminder retreived for predicate: %@", predicate);
            }
        }

        // get the mapview controller off of the navigation stack
        for (UIViewController *viewController in self.navigationController.viewControllers) {
            if ([viewController isKindOfClass:[MapViewController class]]) { 
                MapViewController *mapVC = (MapViewController *)viewController;
                mapVC.audioURI = [[[self.audioPlayers objectAtIndex:self.selectedCell] url] absoluteString];
                [self.navigationController popToViewController:mapVC animated:YES];
            }
        }
}

因为我感觉到了这可能很重要,这里是locationManager的getter:

And because I get the feeling that it might be important, here's the getter for locationManager:

- (CLLocationManager *)locationManager {
    NSLog(@"MapViewController - locationManager");
    if (_locationManager) {
        return _locationManager;
    } else {
        _locationManager = [[CLLocationManager alloc] init];
        return _locationManager;
    }
}

更新1:通过Apple论坛(我转发的地方)有人提到AlertView只会在前台展示。 NSLog还没有开火。我认为应该可行。

UPDATE 1: Via the Apple forums (where I crossposted) someone mentioned that AlertView will only show in the foreground. Still the NSLog doesn't fire either. I'm assuming that should work.

推荐答案

我的一位朋友写了一篇关于使用地理围栏的好教程,可能有助于清理您遇到的一些问题。

A friend of mine wrote up a nice tutorial on using geofencing that might help clear up some issues you are having.

开始使用地理围栏

网上有很多例子,这里有SO。从小处着手,继续前进。一旦开始获得回调,您就可以开始将其扩展到其他视图控制器。

There are plenty of examples online and here on SO. Start out small and work your way up. Once you start getting your callbacks, you can start expanding things out to your other view controllers.

更新

如评论中所述,创建单例类来控制位置管理器和委托方法的好处。通过使用单例,可以防止多次调用委托方法。您可以通过仔细编码来防止这种情况,但使用单例可以为您做到这一点。这也是一个很好的类来处理你的委托方法需要完成的所有工作。

As explained in the comments the benefits of creating a singleton class to control your location manager and delegate methods. By using a singleton, you prevent the possibility of getting multiple calls to your delegate methods. You can prevent this by careful coding, but using a singleton does this for you. This is also a nice class to handle all the work needing to be done by your delegate methods.

这篇关于didEnterRegion在前台工作,但不在后台或其他VC工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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