对多个iBeacons做出反应

时间:2014-04-25 15:32:46

标签: ios objective-c bluetooth-lowenergy ibeacon

我已经和iBeacons玩了几个星期了,并且想知道是否有可能从同一个视图控制器监视两个信标。

例如,到目前为止,我已经创建了一个具有三个特定视图的应用程序,每个视图都对单独的信标作出反应,根据范围改变内容并触发音乐和视频等动态内容。所有这些视图都是相同的布局,所以我想知道我是否可以更改它,所以我有一个视图控制器根据我附近的信标改变内容,而不是必须更改视图。

这样更有意义,因为你只能监控一个意味着当segue触发并且新信标被监控时,如果你向第一个信标移动,当你进入时,它不会回到那个视图。第一个信标接近。

我确信有一种方法可以做到这一点,因为在美国的苹果商店使用信标触发促销等等,并且他们在没有问题的情况下依靠最近的信标。

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@interface ExhibitsViewController : UIViewController <CLLocationManagerDelegate,UIScrollViewDelegate>
{
CLBeacon *beacon;
}

@property (strong, nonatomic) CLBeaconRegion *beaconRegion;
@property (strong, nonatomic) CLLocationManager *locationManager

@end

这是我头文件中定义beacon,beaconRegion和locationManager的代码。

#import "MultipleBeaconsViewController.h"

@interface MultipleBeaconsViewController ()  
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UILabel *rangeLabel;
@property (weak, nonatomic) IBOutlet UILabel *uuidLabel;
@end

@implementation MultipleBeaconsViewController

NSUUID *iBeacon1uuid;
NSUUID *iBeacon2uuid;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
    // Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.

self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self initRegion];

[self locationManager:self.locationManager didStartMonitoringForRegion:self.iBeacon1Region];
[self locationManager:self.locationManager didStartMonitoringForRegion:self.iBeacon2Region];

}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void)initRegion {

iBeacon1uuid = [[NSUUID alloc] initWithUUIDString:@"11111111-2222-3333-4444-555555555555"];
_iBeacon1Region = [[CLBeaconRegion alloc] initWithProximityUUID:iBeacon1uuid identifier:@"com.private.Gallery"];
_iBeacon1Region.notifyOnEntry = YES;
_iBeacon1Region.notifyOnExit = YES;

// launch app when display is turned on and inside region
_iBeacon1Region.notifyEntryStateOnDisplay = YES;

if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
    [_locationManager startMonitoringForRegion:_iBeacon1Region];
    [_locationManager startRangingBeaconsInRegion:_iBeacon1Region];
}

iBeacon2uuid = [[NSUUID alloc] initWithUUIDString:@"55555555-4444-3333-2222-111111111111"];
_iBeacon2Region = [[CLBeaconRegion alloc] initWithProximityUUID:iBeacon2uuid identifier:@"com.private.Gallery"];
_iBeacon2Region.notifyOnEntry = YES;
_iBeacon2Region.notifyOnExit = YES;

// launch app when display is turned on and inside region
_iBeacon2Region.notifyEntryStateOnDisplay = YES;

if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
    [_locationManager startMonitoringForRegion:_iBeacon2Region];
    [_locationManager startRangingBeaconsInRegion:_iBeacon2Region];
}
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {

if ([region isKindOfClass:[CLBeaconRegion class]])
{

    CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;

    if ([beaconRegion.proximityUUID isEqual: iBeacon1uuid])
    {
        _titleLabel.text = @"Beacon 1 proximity entered";

    }
    else if ([beaconRegion.proximityUUID isEqual: iBeacon2uuid])
    {
        _titleLabel.text = @"Beacon 2 proximity entered";
    }

}

}

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{

if ([region isKindOfClass:[CLBeaconRegion class]]) {

    CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;


    if ([beaconRegion.proximityUUID isEqual: iBeacon1uuid])
    {

        _titleLabel.text = @"Beacon 1 proximity exited";
    }
    else if ([beaconRegion.proximityUUID isEqual: iBeacon2uuid])
    {

        _titleLabel.text = @"Beacon 2 proximity exited";
    }

}
}

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{

if ([region isKindOfClass:[CLBeaconRegion class]]) {

    for (CLBeacon *beacon in beacons)
    {

        NSString *beaconID = [beacons objectAtIndex:0];
        NSLog(@"%@",beaconID);

        if ([region.proximityUUID isEqual:iBeacon1uuid])
        {

            if (beacon.accuracy >=0.000001 && beacon.accuracy <=0.500000)
            {
            _titleLabel.text = @"Beacon 1";
            _rangeLabel.text = [NSString stringWithFormat:@"%f",beacon.accuracy];
            _uuidLabel.text = [NSString stringWithFormat:@"%@", beacon.proximityUUID];
            }
        }
        else if ([region.proximityUUID isEqual:iBeacon2uuid])
        {
            if (beacon.accuracy >=0.000001 && beacon.accuracy <=0.500000) {
                _titleLabel.text = @"Beacon 2";
                _rangeLabel.text = [NSString stringWithFormat:@"%f",beacon.accuracy];
                _uuidLabel.text = [NSString stringWithFormat:@"%@", beacon.proximityUUID];
            }
            else
            {

            }
        }

    }
}
}

这是我在实施文件中的代码,它是信标的范围。

3 个答案:

答案 0 :(得分:4)

是的,你可以。要做到这一点,你不必保留属性self.beaconRegion你只需创建任意多个并开始监视并开始测距,例如我就是这样做的:

// Reion 1

CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:major minor:minor identifier:identifier];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
// launch app when display is turned on and inside region
region.notifyEntryStateOnDisplay = YES;

if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
    [_locationManager startMonitoringForRegion:region];
    [_locationManager startRangingBeaconsInRegion:region];
}

// Region 2

   CLBeaconRegion *region2 = [[CLBeaconRegion alloc] initWithProximityUUID:uuid2 major:major2 minor:minor2 identifier:identifier2];
    region2.notifyOnEntry = YES;
    region2.notifyOnExit = YES;
    // launch app when display is turned on and inside region
    region2.notifyEntryStateOnDisplay = YES;

    if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
    {
        [_locationManager startMonitoringForRegion:region2];
        [_locationManager startRangingBeaconsInRegion:region2];
    }

//等等

在每个self.locationManager委托方法之后,确保您拥有哪个信标,例如:

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {

    if ([region isKindOfClass:[CLBeaconRegion class]]) {
        CLBeaconRegion *beaconRegion = (CLBeaconRegion *)region;

        // Find out which beacon you have,
        // I check just UUID but maybe your beacons have the same uuid but major, minor are difference so you need to check minor/major as well
        if ([beaconRegion.proximityUUID isEqual:UUIDFIRST]) {

            //Do some stuff
        }
    }
}

如果您想查看哪个灯塔最近,请使用:

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region

枚举信标数组:

if ([region isKindOfClass:[CLBeaconRegion class]]) {

        for (CLBeacon *beacon in beacons) { // 1
            // do the checking which beacon you have
            if ([beaconRegion.proximityUUID isEqual:UUIDFIRST]) { // 2

            }

                 // check beacon.accuracy property this should gives you distance in meters meters
                 //beacon.accuracy // 3
            }
        }
    }

//扩展

如果您在两个(或更多)信标范围内,信标将以信标数组传递给您。通过调用[beacons lastObject],你只需要一个信标。您需要做的是枚举(遍及数组中的所有对象)在上面的代码中看到没有1(我编辑了一下)并看到你有什么信标(2)之后你比较距离(3)和价值较低的那个是最近的一个。

答案 1 :(得分:3)

UUID可以在许多iBeacons上重复使用。每个信标都有一个主要数字和一个次要数字,以区分每个信标。

所以一家公司会购买一个UUID,但是(以商店为准),

所有专业= 1都在一楼:

  • 未成年人1 =穿着女式服装
  • minor 2 =男装

少校2 =二楼:

  • minor 1 =童装
  • minor 2 =鞋

......等等。当应用程序在商店周围走动时,信标可以告诉它们在哪里,并根据数据提供广告/视频。

您在didRangeBeacons回调中检查这些值。我还相信一个应用程序可以同时监控多达20个区域,因此该回调中的region属性将包含不同的UUID

答案 2 :(得分:0)

中提供的标识符
[[CLBeaconRegion alloc] initWithProximityUUID:iBeacon1uuid identifier:@"com.private.Gallery"]; 
对于您正在监控的每个信标,

必须不同。

在你的情况下,他们都是@“com.private.Gallery”