作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我注意到,每当我再次启动该应用程序 并查看以下方法时,我发现返回的 beaconRegion 不为空。这究竟是如何工作的?
beaconRegion = [self.locationManager.monitoredRegions member:beaconRegion];
// for more context on how I use this please look at the code below
换句话说,iOS如何处理CLLocationManager的分配?每次唤醒应用程序时,它是否反序列化它并以这种方式检索区域信息?
这是运行以下代码时 Xcode 调试器控制台的输出:
2015-11-11 09:44:13.718 RegionMonitoringTest[239:15121] AppDelegate: creating new location manager object
2015-11-11 09:44:13.722 RegionMonitoringTest[239:15121] BeaconMonitoring class: in startRangingForBeacons, startupdatinglocation, range for my beacon
2015-11-11 09:44:13.724 RegionMonitoringTest[239:15121] Region already in list
2015-11-11 09:44:13.732 RegionMonitoringTest[239:15121] AppDelegate: Application did became active.
2015-11-11 09:44:13.762 RegionMonitoringTest[239:15121] BeaconMonitoring -> LocationManager: didFailWithError | Error: Error Domain=kCLErrorDomain Code=0 "(null)"
2015-11-11 09:44:13.762 RegionMonitoringTest[239:15121] Requesting to start ranging for beacons again.
2015-11-11 09:44:13.762 RegionMonitoringTest[239:15121] BeaconMonitoring class: in startRangingForBeacons, startupdatinglocation, range for my beacon
2015-11-11 09:44:13.767 RegionMonitoringTest[239:15121] Region already in list
下面我粘贴了我用来测试这个的源代码,它可能会有所帮助(它基于 Apple 提供的 AirLocate 示例):
#import "AppDelegate.h"
#define BEACON_REGION @"01020102-0102-0102-0102-010201020102"
@interface AppDelegate ()
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) NSMutableArray * monitoredRegions;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
NSLog(@"AppDelegate: being woken up after entering region");
}
else{
NSLog(@"AppDelegate: creating new location manager object");
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.pausesLocationUpdatesAutomatically = false;
self.locationManager.allowsBackgroundLocationUpdates = true;
self.locationManager.delegate = self;
if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
self.monitoredRegions = [[NSMutableArray alloc] initWithCapacity:10];
[self startRangingForBeacons];
}
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
NSLog(@"AppDelegate: will resign active");
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
NSLog(@"AppDelegate: did enter background");
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
//[self.bluetoothDataSync stopScanning];
NSLog(@"AppDelegate: did enter foreground");
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
NSLog(@"AppDelegate: Application did became active.");
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
//[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSLog(@"AppDelegate: App will terminate");
}
//////////////////////////////////////////////////
- (void) startRangingForBeacons{
NSLog(@"BeaconMonitoring class: in startRangingForBeacons, startupdatinglocation, range for my beacon");
[self startMonitoringForRegion:[[NSUUID alloc] initWithUUIDString:BEACON_REGION] :@"my-beaconregion"];
}
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error {
NSString * message = [NSString stringWithFormat:@"BeaconMonitoring -> LocationManager: monitoringDidFailForRegion | Error: %@, Region identifier: %@", error, region.identifier];
NSLog(@"%@", message);
NSLog(@"Requesting to start ranging for beacons again.");
[self startRangingForBeacons];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSString * message = [NSString stringWithFormat:@"BeaconMonitoring -> LocationManager: didFailWithError | Error: %@", error];
NSLog(@"%@", message);
NSLog(@"Requesting to start ranging for beacons again.");
[self startRangingForBeacons];
}
- (void) startMonitoringForRegion:(NSUUID*)beaconUUID :(NSString*)regionIdentifier{
CLBeaconRegion *beaconRegion = nil;
beaconRegion = [self.locationManager.monitoredRegions member:beaconRegion];
if(beaconRegion)
{
NSLog(@"Region already in list");
}
else{
beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconUUID identifier:regionIdentifier];
beaconRegion.notifyEntryStateOnDisplay = YES;
beaconRegion.notifyOnEntry = YES;
beaconRegion.notifyOnExit = YES;
[self.locationManager startMonitoringForRegion:beaconRegion];
}
[self.locationManager startRangingBeaconsInRegion:beaconRegion];
[self.locationManager startUpdatingLocation];
[self.monitoredRegions addObject:beaconRegion];
}
- (void) stopRangingForbeacons{
NSLog(@"BeaconMonitoring: stopRangingForbeacons - Stops updating location");
[self.locationManager stopUpdatingLocation];
for (int i=0; i < [self.monitoredRegions count]; i++) {
NSObject * object = [self.monitoredRegions objectAtIndex:i];
if ([object isKindOfClass:[CLBeaconRegion class]]) {
CLBeaconRegion * region = (CLBeaconRegion*)object;
[self.locationManager stopMonitoringForRegion:region];
[self.locationManager stopRangingBeaconsInRegion:region];
}
else{
NSLog(@"BeaconMonitoring: unrecongized object in beacon region list");
}
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
if (![CLLocationManager locationServicesEnabled]) {
NSLog(@"Couldn't turn on ranging: Location services are not enabled.");
}
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) {
NSLog(@"Couldn't turn on monitoring: Location services not authorised.");
}
}
#pragma CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(@"BeaconMonitoring: did enter region, will now start ranging beacons in this region");
[manager startRangingBeaconsInRegion:(CLBeaconRegion*)region];
[self.locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(@"BeaconMonitoring: did exit region, will now: stop ranging beacons in this region; stop updating locations; stop scanning for BLE");
[manager stopRangingBeaconsInRegion:(CLBeaconRegion*)region];
[self.locationManager stopUpdatingLocation];
NSDictionary * notificationData = @{ @"value" : @"exitedRegion"};
[[NSNotificationCenter defaultCenter] postNotificationName:@"dataUpdate" object:nil userInfo:notificationData];
}
- (void) locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
NSString * message = @"CLRegionState: ";
switch (state) {
case CLRegionStateInside:
message = @"CLRegionState: state inside";
break;
case CLRegionStateOutside:
message = @"CLRegionState: state outside";
break;
case CLRegionStateUnknown:
message = @"CLRegionState: state unknown";
break;
default:
message = @"CLRegionState: default case";
break;
}
NSLog(@"%@", message);
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
bool rangedBeacons = false;
if ([beacons count]>0) {
for (int i=0; i<[beacons count]; i++) {
CLBeacon *beacon = [beacons objectAtIndex:i];
if((beacon.major.intValue == 4) && (beacon.major.intValue == 8)){
rangedBeacons = true;
}
}
}
if (rangedBeacons) {
NSLog(@"Region identifier: %@", region.identifier);
NSString * message = [NSString stringWithFormat:@"BeaconMonitoring: ranged a total of %lu, hence request scan start", (unsigned long)[beacons count]];
NSLog(@"%@", message);
}
}
最佳答案
由于位置管理器的监控即使在应用程序未运行时也能正常工作,例如,由于内存压力而终止或在应用程序切换器处被用户杀死,iOS 需要保留应用程序监控区域列表以供应用程序外部的某个地方使用,您可以将 monitoredRegions
视为该列表的反射(reflect),而不是在对象被释放时消失的实例属性。
请注意,例如,如果您实例化多个位置管理器,它们都共享相同的监控列表——列表在操作系统级别的某个位置按应用存储的直接结果。如果您在一个位置管理器中开始/停止监视某个区域,它将影响所有其他区域。
所有这些都适用于 CLBeaconRegion
,但也适用于“常规”CLCircularRegion
— 因为它是一种监视功能,而不是特定于信标的东西。
关于ios - 信标区域监控应用程序的 CLLocationManager 的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33647975/
我是一名优秀的程序员,十分优秀!