如果应用程序正在运行且CLLocationManagerDelegate类是前台(即可见),那么didEnterRegions会触发,我同时获得NSLog以及AlertView。但是,当应用程序在后台时,或者,如果屏幕显示除委托类之外的其他内容,我什么也得不到。
我在plist中的“Required background modes”下设置了“App registers for location updates”,虽然我不确定是否有必要。
这就是我认为的相关代码,虽然我可能错了(并且很乐意添加更多)。我应该注意viewDidLoad中的所有内容都包含在if中,检查区域监视是否可用并启用。
- (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中获取受监控区域列表的地方:
- (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,这里是主要的地方:
- (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:
- (CLLocationManager *)locationManager {
NSLog(@"MapViewController - locationManager");
if (_locationManager) {
return _locationManager;
} else {
_locationManager = [[CLLocationManager alloc] init];
return _locationManager;
}
}
更新1:通过Apple论坛(我转发的地方)有人提到AlertView只会在前台显示。 NSLog还没有开火。我认为应该可行。
答案 0 :(得分:3)
我的一位朋友写了一篇关于使用地理围栏的好教程,这可能有助于解决你遇到的一些问题。
网上有大量的例子,这里有SO。从小处着手,继续前进。一旦开始获得回调,就可以开始将其扩展到其他视图控制器。
更新
如评论中所述,创建单例类来控制位置管理器和委托方法的好处。通过使用单例,可以防止多次调用委托方法。您可以通过仔细编码来防止这种情况,但使用单例可以为您做到这一点。这也是一个很好的类来处理你的委托方法需要完成的所有工作。
答案 1 :(得分:2)
你做错了什么:
例如。通知:
-(void)triggerLocalNotification:(CLRegion *)region{
UILocalNotification *notification = [[UILocalNotification alloc]init];
[notification setAlertBody:[NSString stringWithFormat:@"Welcome to %@", [region identifier]]];
[notification setRepeatInterval:0];
[notification setFireDate:[NSDate dateWithTimeIntervalSinceNow:2]];
[notification setTimeZone:[NSTimeZone defaultTimeZone]];
[[UIApplication sharedApplication]scheduleLocalNotification:notification];
NSLog(@"notification triggered with notification %@", notification);
}
答案 2 :(得分:0)
您可以在执行EnnterRegion时发布本地通知。
即使您在后台,也会显示类似警报的弹出窗口。
你可以做一个简单的测试:
1)在app delegate的applicationDidEnterBackground中创建一个本地通知对象,包含任意随机消息并告知本地通知立即触发。
2)按主页按钮,当应用最小化时,您应该看到一个弹出窗口。
答案 3 :(得分:0)
我认为你需要去你的app.plist
并添加必需的背景模式:添加itme App寄存器以进行位置更新
和1。如果你的应用程序在后台,你仍然会看到顶部的箭头
和2,如果应用程序被杀,你仍然可以在顶部看到一个空心箭头,ios将为你监控该区域,但仅限于20个区域