I'm using the air locate example and monitoring for iBeacons by uuid only. When I get the entered region event, I can't seem to get the major and minor from the beacon/region that has triggered the event if I'm only looking for the uuid (I can if I'm monitoring for a uuid with specified major and minor) - does anyone know a way to do this/am I missing something?
I don't really want to start ranging - doesn't seem like I should need to..
(The use case is for say lots of stores all with beacons with the same uuid, then issuing an OS notification with relevant information about that store (obtained by querying the major and minor))
Here's basically what I do:
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:@"blah"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
region.notifyEntryStateOnDisplay = YES;
[self.locationManager startMonitoringForRegion:region];
Then in the app delegate:
- (void) locationManager:(CLocationManager*)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion*)region {
// assume for now its the iBeacon
CLBeaconRegion *beaconRegion = (CLBeaconRegion*) region;
beaconRegion.major // hasn't been set...
}
Many Thanks!
You're not doing anything wrong. Surprising as it may seem, the monitoring API doesn't give you the specific beacon(s) that triggered the region change.
The reason the major isn't set on the CLBeaconRegion object is because that is the exact same object you used to start monitoring, and you set that field to nil (or didn't set it at all leaving it nil). What you are looking for is an additional array of CLBeacon objects. And as you suggest, this is only present on the Ranging APIs.
It really isn't a big deal to start ranging. Just set it up at the exact same time as you start monitoring:
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:@"blah"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
region.notifyEntryStateOnDisplay = YES;
[self.locationManager startMonitoringForRegion:region];
[self.locationManager startRangingBeaconsInRegion:region];
And if you only care about the first ranging call, you can use a flag to ignore further updates:
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
if (!_firstOneSeen) {
// Do something with beacons array here
}
}
And reset that flag when you leave the region
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
_firstOneSeen = NO;
}
As a bonus, this will also make your monitoring response times much faster when your app is in the foreground. See: http://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html