iBeacon:获取major和minor - 只关注UUID

7
我正在使用Air Locate示例,并仅通过UUID监视iBeacon。当我收到进入区域事件时,如果我只监视UUID(如果我监视带有指定major和minor的UUID则可以),似乎无法从触发事件的信标/区域获取major和minor - 有人知道如何解决这个问题吗?或者我是否遗漏了什么?
我不想开始扫描 - 似乎我不应该需要..
(用例是例如有许多带有相同UUID的商店,然后发出包含有关该商店的相关信息的操作系统通知(通过查询major和minor获得))
这里是我基本上要做的事情:
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:@"blah"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
region.notifyEntryStateOnDisplay = YES;

[self.locationManager startMonitoringForRegion:region];

然后在应用程序代理中:

- (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...

}

非常感谢!

3个回答

20

你没有做错任何事情。虽然看起来令人惊讶,但监视API不会给出触发区域更改的具体信标。

主要原因是CLBeaconRegion对象上没有设置major,因为那正是您用于开始监视的完全相同的对象,并且您将该字段设置为nil(或者根本没有设置它,使其保持nil)。您需要的是另一个CLBeacon对象数组。正如您所建议的那样,这仅存在于Ranging API中。

启动Ranging确实并不是什么大问题。只需在开始监控的同时进行设置:

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]; 

如果您只关心第一次距离调用,可以使用一个标志来忽略后续的更新:

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
    if (!_firstOneSeen) { 
        // Do something with beacons array here
    }
}

当您离开该区域时,请重置该标志。

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    _firstOneSeen = NO;
}
作为奖励,当您的应用程序处于前台时,这也将使您的监视响应时间更快。请参见:http://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html

非常感谢你,David,这真的很有帮助。还要感谢你提供的其他无价的 SO 答案。 - Matthew
3
好的文章。然而,需要纠正一点。在didEnterRegion/didExitRegion调用中获得的region对象并不是您用于注册的CLBeaconRegion对象本身-它是一个副本。我知道这是因为我最初尝试使用if(region == regionImTracking)这样的代码进行比较,但是比较失败了。我记录了这两个区域,它们的地址不同,而它们的所有设置都匹配。 - Duncan C
有没有官方文档明确说明这是不可能的?我知道这是真的,但我必须向管理层解释,并指出除了人们“做出假设”之外的其他东西。谢谢。 - Herz Rod
官方文档可能没有明确说明以便于所有经理理解,但它确实是这样说的。请参见以下页面上的locationManager:didDetermineState:forRegion:部分,并注意它将传递的区域对象描述为“确定状态的区域”,该区域对象不包含iBeacon标识符。https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html - davidgyoung

4
很遗憾,如果你只以UUID为基础进行监测,确定major和minor只能在iBeacon ranging API中完成,而非iBeacon monitoring API。此外,
1)当您的应用程序处于后台时,iBeacon ranging无法工作。这意味着,如果您的应用程序在后台运行(对于这些类型的应用程序大多数情况下都是如此),除非您基于UUID、major和minor进行监测,否则无法确定iBeacon的major和minor。
2)同时最多只能监测20个iBeacons。这意味着,如果您采用基于UUID、major和minor的监测方式(为了解决后台ranging问题),您将被限制在仅有的20个iBeacon上(在大多数实际情况下是一个很大的限制)。
3)为了实现最大扩展性(因为您只能同时监测20个iBeacons),最好只通过UUID进行监测,在检测到该UUID的iBeacon时通知用户,并在通知后用户可以确认将应用程序带入前台。一旦应用程序在前台,就可以进行ranging以确定iBeacon的major和minor。
所有这些引发了我的疑问,为什么苹果公司没有在监测API中首先包含触发进入/退出的iBeacon数组。我留下这个让苹果公司发表评论。以下帖子详细介绍了这些iBeacon的行为/限制-在后台使用iBeacon - Use cases

你可能想要查看你链接的问题中关于后台范围的评论。 - Chris Stratton

0
  • CLBeaconRegion是用于查找信标的筛选条件。所以当“didEnterRegion”委托触发时,你传入的内容就是你将要得到的内容。没有什么意外。

  • CLBeacon是符合筛选条件并触发didEnterRegion委托的单个信标。在这里,你可以找到主要和次要值。要获取触发的信标,你需要调用范围API startRangingBeaconsInRegion,并在停止范围之前给它一个计数为5。在收到didEnterRegion回调后执行此操作。这适用于对信标进行后台监控的情况,当你不想启动应用程序,只是记录用户经过信标的时间,以便在服务器上构建智能化的广告活动。

有时候范围可能找不到任何信标,在这种情况下,使用回调中的beaconRegion来记录某人进入了信标区域。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接