iBeacon:didRangeBeacons停止调用,必须重置设备才能再次正常工作

13

我正在使用自定义的BeaconManager代理,以便Beacon Ranging不受视图控制器生命周期的影响。一切都很好,但偶尔(1-2天)Beacon Ranging会停止工作,didRangeBeacons永远不会被调用。唯一的解决方法是重置我的iPhone,一旦这样做,它就能完美地工作。以下是我正在使用的代码。基本流程是,当我的ViewController调用ViewDidLoad时,它会向AppDelegate发送一个通知,告诉它开始搜索Beacons,然后我从未告诉它停止搜索,因为我希望它在用户导航到应用程序中的任何位置时都继续搜索Beacons。我想知道这是否是我的代码引起的问题,还是蓝牙存在错误。感谢您的帮助!

BeaconManager.m

#import "BeaconManager.h"
#import "AppDelegate.h"

@interface BeaconManager()<CLLocationManagerDelegate>

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

@end

@implementation BeaconManager

+ (id)sharedManager
{
    static BeaconManager *sharedBeaconManager = nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        sharedBeaconManager = [[self alloc] init];
    });
    return sharedBeaconManager;
}

- (id)init
{
    self = [super init];
    if(self)
    {
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
    }
    return self;
}

- (void)startBeaconMonitoring:(NSString*)forUUID
{
    NSUUID * uuid = [[NSUUID alloc] initWithUUIDString:forUUID];

    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.beacons.publicRegion"];
    [self.locationManager startMonitoringForRegion:self.beaconRegion];
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}

- (void)stopBeaconMonitoring
{
    //Stop the region monitoring
    if(self.locationManager != nil && self.beaconRegion != nil) {
        [self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
    }
}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
    self.beacons = beacons;
    if(self.delegate != nil) {
        [self.delegate beaconManager:self didRangeBeacons:self.beacons];
    }
}

@end

视图控制器.m

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"startRanging" object:nil userInfo:nil];
}

AppDelegate.m

->

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startRangingForZombies) name:@"startRanging" object: nil];

    return YES;
}

- (void)startRanging
{
    //Start the beacon region monitoring when the controller loads
    BeaconManager *beaconManager = [BeaconManager sharedManager];
    beaconManager.delegate = self;
    [beaconManager startBeaconMonitoring:@"1234-54324-34242-34242-43243"];
}
5个回答

21
我们在Radius Networks收到了很多关于手机停止检测iBeacons并需要重新启动或关闭蓝牙再次启动以解决问题的报告。人们已经在iPhone 4S、iPhone 5s、iPhone 5c和iPad上报告了这个问题。
我没有任何确凿的证据表明这是iOS 7.1之后出现的问题,但自从发布以来报告频率大大增加。因此,间接证据相当有力。
当手机处于这种状态时,手机仍然可以扫描蓝牙设备,并且仍然可以作为iBeacon进行传输。因此,这不是蓝牙硬件问题。根据现有证据,最可能是CoreLocation中新引入的错误。

David,由于didRangeBeacons方法没有被调用,这个问题是否会触发rangingBeaconsDidFailForRegion方法呢?这对我来说很难测试,因为它只是偶尔发生,但我只是好奇你是否知道这个问题是否会触发那个方法,谢谢! - Patrick
不,我不相信这个方法会被调用。我的理解是,除了CoreLocation无法检测iBeacon之外,所有蓝牙功能都正常工作。这不是一个失败,而是因为iOS没有执行必要的蓝牙扫描来寻找信标。 - davidgyoung
系统版本低于7.1的iPhone不会出现这个问题,所以几乎可以确定不是硬件问题。我同时在4S 7和4S 7.1上使用信标,7没有任何问题(甚至一次都没有),而我不得不每天重启7.1几次,所以我的猜测是这是一个系统问题。 - Kamil Tustanowski
7
上周在WWDC上,我与Core Location团队成员交谈,他们表示已经意识到该问题,并将在今年稍后的iOS 7.1更新中进行修复,同时也会在iOS 8中修复。虽然没有关于具体时间表的细节信息。 - Markus Rautopuro
现在7.1.2已经发布了,有人能确认同样的错误在7.1.2中是否仍然存在吗? - Alex Su
1
完全还在看到这个,这是许多问题的症状。我以前在Android上经常看到它,直到我变得更好之后,现在我在swift上也经常看到它(这是将近3年后)。 - Saik Caskey

5
实际上,这是iOS 7.1中已知的一个bug。这是与最新版本iOS的蓝牙堆栈有关的严格的软件问题。蓝牙设备检测有时会突然停止工作 - 不幸的是,这对所有兼容iOS 7.1的设备都适用。该漏洞已经向苹果报告,但只要他们不为此发布修复程序,最好的解决方案就是重新启动设备。
如果重新启动无效,SmartRobotic提供了一个方便的指南来解决这个问题:http://www.smartbotics.com/#!4-Tips-to-Fix-Bluetooth-Problems-After-iOS-71-Upgrade/c118r/031A86F6-C8E8-4768-B4FD-E6F83D9E4317 如果您在升级到iOS 7.1后遇到蓝牙连接问题,请尝试以下4个提示:
1. 关闭并重启设备 - 有些人报告说这就是他们在iOS 7.1升级后修复设备所需的全部步骤。 2. 切换蓝牙开关 - 向上滑动以访问控制中心,然后点击蓝牙图标,等待至少30秒,然后切换回来。这通常可以修复遇到连接问题的设备。 3. 关闭(强制退出)有问题的应用程序 - 首先双击主屏幕以启动多任务卡片界面。触摸并按住应用程序的卡片,然后将其向上扔掉。这将强制应用程序退出,并在下次打开应用程序时完全重新加载。 4. 清除并重置您的蓝牙设备配对 - 转到“设置”>“蓝牙”,然后点击有问题的设备的(i)图标。点击“忘记此设备”。现在,您应该能够重新添加和重新配对蓝牙硬件到您的设备。要清除所有配对设备,请转到“设置”>“通用”>“重置”>“重置网络设置”,然后再次设置您的蓝牙配对。
希望这些建议能解决您的蓝牙连接问题。

很好,我很高兴这是一个已知的问题,而不是我的代码格式的问题。 - Patrick

2

好消息是很多人都遇到了这个问题,希望苹果能尽快修复。感谢您的见解! - Patrick

2

苹果在7.1版本中对蓝牙低功耗进行了重要更改,但同时也破坏了一些功能。

通过我的实验:

  • iPhone 4S 7.x - iBeacons功能非常好用

  • 2个 iPhone 4S 7.1 和 2个 iPhone 5 7.1 - 功能正常,但需要不定期地重新启动。

看起来这是系统问题 - 一个大问题。我已经联系了Estimote - 他们知道这个问题。

有趣的事实:你无法找到beacons - 即使estimote演示应用程序也无法找到,代理方法也没有被调用,但是您可以将(损坏的)设备变成信标,并且其他设备可以发现它。


那么这就不是我的代码问题了?这是最新更新中已知的一个 bug? - Patrick
Kamil,由于didRangeBeacons方法没有被调用,这个问题会触发rangingBeaconsDidFailForRegion方法吗?这很难测试,因为它只是偶尔发生,但我只是好奇你是否知道这个问题是否会触发那个方法,谢谢! - Patrick

0

我曾经遇到过类似的问题,但是经过一段时间的调查研究后,我意识到在连续调用startMonitoringForRegion(region)和startRangingBeaconsInRegion(region)是错误的。这正是你(Patrick)所做的:

- (void)startBeaconMonitoring:(NSString*)forUUID {
     NSUUID * uuid = [[NSUUID alloc] initWithUUIDString:forUUID];

     self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.beacons.publicRegion"];
     [self.locationManager startMonitoringForRegion:self.beaconRegion];
     [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}

相反,应该在locationManagerDelegate方法locationManager(manager:CLLocationManager!,didDetermineState state:CLRegionState,forRegion region:CLRegion!)中调用startRangingBeaconsInRegion(region)(在这种情况下是Swift代码)。 这是我的解决方案。

这很有道理,因为第一步是在区域中查找任何信标,第二步是从已监视的信标获取特定信息。


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