Question

I've been through two tutorials and am reading up on basic C. Learn best through doing and have written a few light apps in the past week or so. Am getting up to speed to write some apps that will use ibeacon. As I'm going through some samples and reading the reference guide I see that multiple regions can be scanned by running startMonitoringForRegion for each UUID. OK, so I figure I could just run it for each UUID but that's not working. I'm sure I'm doing something basic totally wrong... the code below is a total hack - once I get the semantics I will pull the UUIDs from a DB with an API call and than loop through them to activate the monitoring. The code below results in last loop only showing two of the four UUIDs.

in header:

@property (strong, nonatomic) CLBeaconRegion *myBeaconRegion;
@property (strong, nonatomic) CLBeaconRegion *myBeaconRegion2;
@property (strong, nonatomic) CLBeaconRegion *myBeaconRegion3;
@property (strong, nonatomic) CLBeaconRegion *myBeaconRegion4;

in main:

NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"86E4BDEA-C6FF-442C-95CB-E6E557A23CF2"];
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.appcoda.testregion"];

NSUUID *uuid2 = [[NSUUID alloc] initWithUUIDString:@"C9AFF296-A722-4F2D-8669-47B7CCC79A14"];
self.myBeaconRegion2 = [[CLBeaconRegion alloc] initWithProximityUUID:uuid2 identifier:@"com.appcoda.testregion"];

NSUUID *uuid3 = [[NSUUID alloc] initWithUUIDString:@"1DBDDC7C-49BB-48BF-A2F6-A4825BD514EA"];
self.myBeaconRegion3 = [[CLBeaconRegion alloc] initWithProximityUUID:uuid3 identifier:@"com.appcoda.testregion"];

NSUUID *uuid4 = [[NSUUID alloc] initWithUUIDString:@"8D942B9E-0197-4C81-8722-92144599E9F7"];
self.myBeaconRegion4 = [[CLBeaconRegion alloc] initWithProximityUUID:uuid4 identifier:@"com.appcoda.testregion"];

[self.locationManager startMonitoringForRegion:self.myBeaconRegion];
[self.locationManager startMonitoringForRegion:self.myBeaconRegion2];
[self.locationManager startMonitoringForRegion:self.myBeaconRegion3];
[self.locationManager startMonitoringForRegion:self.myBeaconRegion4];

NSSet *setOfRegions = [self.locationManager monitoredRegions];
    for (CLRegion *region in setOfRegions) {
        NSLog (@"region info: %@", region);
    }
Was it helpful?

Solution

I think the problem is your region identifiers. Each beacon region identifier must be unique, otherwise CLLocationManager treats them as the same region.

Try setting a unique identifier for each region:

NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"86E4BDEA-C6FF-442C-95CB-E6E557A23CF2"];
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.appcoda.testregion"];

NSUUID *uuid2 = [[NSUUID alloc] initWithUUIDString:@"C9AFF296-A722-4F2D-8669-47B7CCC79A14"];
self.myBeaconRegion2 = [[CLBeaconRegion alloc] initWithProximityUUID:uuid2 identifier:@"com.appcoda.testregion2"];

NSUUID *uuid3 = [[NSUUID alloc] initWithUUIDString:@"1DBDDC7C-49BB-48BF-A2F6-A4825BD514EA"];
self.myBeaconRegion3 = [[CLBeaconRegion alloc] initWithProximityUUID:uuid3 identifier:@"com.appcoda.testregion3"];

NSUUID *uuid4 = [[NSUUID alloc] initWithUUIDString:@"8D942B9E-0197-4C81-8722-92144599E9F7"];
self.myBeaconRegion4 = [[CLBeaconRegion alloc] initWithProximityUUID:uuid4 identifier:@"com.appcoda.testregion4"];

You should see each region listed from your NSLog statement. No need for dispatch_async, either.

OTHER TIPS

The header file for startMonitoringForRegion states "This is done asynchronously and may not be immediately reflected in monitoredRegions".

You can verify this by adding a time delay to your for loop:

double delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    NSSet *setOfRegions = [self.locationManager monitoredRegions];
    for (CLRegion *region in setOfRegions) {
        NSLog (@"region info: %@", region);
    }
});

If you need to use multiple beacons to be monitored then you can able to differentiate using the beacon Major and Minor values. Read the tutorial here to understand about the ibeacons better.

-(void)setBeaconTranmitter:(NSInteger)major minorValue:(NSInteger)minor {
    // We need to set beacon regions here.
    NSUUID * uid = [[NSUUID alloc] initWithUUIDString:uuid]; //uuid value is static common string for all beacons.
    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uid major:major minor:minor identifier:beaconsId];//beaconsId is a common identifier for all beacons.
    
// Call your Transmitter function here
    [self configureTransmitter];
}

Above way I have configured three beacons regions with major and minor value difference. I placed three buttons and called IBAction to send different Major and Minor values using tags and calling function. I installed the same app in three different iphones and enabled each different button in each phones and installed a receiver in another phone for demo. Worked like charm! but it takes time to detect region while moving from one region to another.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top