Objective C - 离开时 CBCentralManager NSInternalInconsistencyException ViewController
Objective C - CBCentralManager NSInternalInconsistencyException when leaving ViewController
我是按照 How to get the status of bluetooth (ON/OFF) in iphone programatically 的代码来获取蓝牙状态的。
但是当我通过后退导航按钮弹出 viewController 时,应用程序崩溃并出现以下错误。
[CoreBluetooth] XPC connection invalid
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x170261c80 of class CBCentralManager was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x1aa9c3710, Property: 0x170056b90> Context: 0x1aa9c3710, Property: 0x170056b00> Context: 0x1aa9c3710, Property: 0x170056b90> Context: 0x1aa9c3710, Property: 0x170056b00> )'
我尝试在调用viewWillDisappear时移除上述观察者,但仍然报错
[self.bluetoothManager removeObserver:self forKeyPath:@"state"];
[self.bluetoothManager removeObserver:self forKeyPath:@"delegate"];
我试过了
self.bluetoothManager.delegate = nil;
和
self.bluetoothManager = nil;
遗憾的是他们都没有作品。
请给予帮助。
更新:
我想在调用 - (void)detectBluetooth 时显示系统弹出警报,而蓝牙未打开。所以我添加
[self.bluetoothManager init];
in - (void)detectBluetooth.
我发现犯了这个错误。
但我想不出另一种方法来显示默认弹出窗口(带有设置按钮)。
我找到了发生此错误的根本原因。
我对蓝牙管理器进行了多次初始化,所以它自己分配了多个观察者。
根据我的目的,在蓝牙未打开时显示系统警报弹出窗口。由于 init
会弹出警报,我需要先将 nil
设置为蓝牙管理器,然后再设置 init
。这没有错误。
这是我的最终代码:
if(!self.bluetoothManager)
{
// Put on main queue so we can call UIAlertView from delegate callbacks.
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
} else{
if (self.bluetoothManager.state != CBManagerStatePoweredOn) {
self.bluetoothManager = nil;
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
}
}
[self centralManagerDidUpdateState:self.bluetoothManager];
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch(self.bluetoothManager.state)
{
case CBCentralManagerStatePoweredOn: [self pushViewController]; break;
case CBCentralManagerStateResetting:
case CBCentralManagerStateUnsupported:
case CBCentralManagerStateUnauthorized:
case CBCentralManagerStatePoweredOff:
default: break;
}
}
我是按照 How to get the status of bluetooth (ON/OFF) in iphone programatically 的代码来获取蓝牙状态的。
但是当我通过后退导航按钮弹出 viewController 时,应用程序崩溃并出现以下错误。
[CoreBluetooth] XPC connection invalid
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x170261c80 of class CBCentralManager was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x1aa9c3710, Property: 0x170056b90> Context: 0x1aa9c3710, Property: 0x170056b00> Context: 0x1aa9c3710, Property: 0x170056b90> Context: 0x1aa9c3710, Property: 0x170056b00> )'
我尝试在调用viewWillDisappear时移除上述观察者,但仍然报错
[self.bluetoothManager removeObserver:self forKeyPath:@"state"];
[self.bluetoothManager removeObserver:self forKeyPath:@"delegate"];
我试过了
self.bluetoothManager.delegate = nil;
和
self.bluetoothManager = nil;
遗憾的是他们都没有作品。
请给予帮助。
更新:
我想在调用 - (void)detectBluetooth 时显示系统弹出警报,而蓝牙未打开。所以我添加
[self.bluetoothManager init];
in - (void)detectBluetooth.
我发现犯了这个错误。
但我想不出另一种方法来显示默认弹出窗口(带有设置按钮)。
我找到了发生此错误的根本原因。
我对蓝牙管理器进行了多次初始化,所以它自己分配了多个观察者。
根据我的目的,在蓝牙未打开时显示系统警报弹出窗口。由于 init
会弹出警报,我需要先将 nil
设置为蓝牙管理器,然后再设置 init
。这没有错误。
这是我的最终代码:
if(!self.bluetoothManager)
{
// Put on main queue so we can call UIAlertView from delegate callbacks.
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
} else{
if (self.bluetoothManager.state != CBManagerStatePoweredOn) {
self.bluetoothManager = nil;
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
}
}
[self centralManagerDidUpdateState:self.bluetoothManager];
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch(self.bluetoothManager.state)
{
case CBCentralManagerStatePoweredOn: [self pushViewController]; break;
case CBCentralManagerStateResetting:
case CBCentralManagerStateUnsupported:
case CBCentralManagerStateUnauthorized:
case CBCentralManagerStatePoweredOff:
default: break;
}
}