IOS 蓝牙 LE 扫描设备未添加到 uitableview
Posted
技术标签:
【中文标题】IOS 蓝牙 LE 扫描设备未添加到 uitableview【英文标题】:IOS Bluetooth LE Scanning Devices not adding to the uitableview 【发布时间】:2014-07-11 08:24:18 【问题描述】:我想使用uitableview实现ios的蓝牙扫描和连接模块。在执行方面,没有项目被添加到列表中。你能告诉我我还需要做什么来显示带有设备名称、uuid 等的蓝牙设备列表吗?
例如, 1.如何将我的对象数组设置为uitableview的数据源? 2. 点击时如何处理设备之间的蓝牙连接?
_currentperipheral = peripheral; <--also fails at Thread 1 EXC_BREAKPOINT
以下是我的控制台消息
2014-07-11 16:34:18.286 marker[6060:60b] Scanning started
2014-07-11 17:53:14.056 marker[6115:60b] Discovered WiT Power Meter at -67
下面是我的模型类:
@interface BTDevice : NSObject
NSString *name;
NSString *macAddress;
@property(nonatomic, retain) NSString *name;
@property(nonatomic, retain) NSString *macAddress;
- (NSString *)getName;
- (NSString *)getMacAddress;
- (void)setName:(NSString *)valueName;
- (void)setMacAddress:(NSString *)valueMacAddress;
@end
以下是我的工作:
- (void)viewDidLoad
[super viewDidLoad];
_pendingInit = YES;
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
_currentperipheral=[[CBPeripheral alloc]init];
_founddevice=FALSE;
_foundPeripherals = [[NSMutableArray alloc] init];
_connectedServices = [[NSMutableArray alloc] init];
- (void)viewWillDisappear:(BOOL)animated
[_centralManager stopScan];
NSLog(@"Scanning stopped");
[super viewWillDisappear:animated];
#pragma mark - Table view data source
- (void)tableView: (UITableView *)tableView
didSelectRowAtIndexPath: (NSIndexPath *)indexPath
int idx=indexPath.row;
BTSentCommandViewController * sliderVC = [self.storyboard instantiateViewControllerWithIdentifier:@"BTSentCommandViewController"];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
#warning Potentially incomplete method implementation.
// Return the number of sections.
return [_foundPeripherals count];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
#warning Incomplete method implementation.
// Return the number of rows in the section.
return [_foundPeripherals count];
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
// You should test all scenarios
if (central.state != CBCentralManagerStatePoweredOn)
return;
if (central.state == CBCentralManagerStatePoweredOn)
// Scan for devices
[_centralManager scanForPeripheralsWithServices:nil options:nil];
NSLog(@"Scanning started");
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
NSLog(@"Discovered %@ at %@", peripheral.name, RSSI);
if (_currentperipheral != peripheral)
// Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
_currentperipheral = peripheral;
BTDevice *myDevice=[[BTDevice alloc] init];
[myDevice setName: peripheral.name];
NSString * macAddress = [NSString stringWithFormat:@"%@" , peripheral.RSSI];
[myDevice setMacAddress: macAddress] ;
[_foundPeripherals addObject:myDevice ] ;
[self.tableView reloadData];
NSLog(@"Connecting to peripheral %@", peripheral);
[_centralManager connectPeripheral:peripheral options:nil];
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
NSLog(@"Failed to connect");
[self cleanup];
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
NSLog(@"Connected");
[_centralManager stopScan];
NSLog(@"Scanning stopped");
peripheral.delegate = self;
[peripheral discoverServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]];
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
if (error)
[self cleanup];
return;
for (CBService *service in peripheral.services)
[peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service];
// Discover other characteristics
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
if (error)
[self cleanup];
return;
for (CBCharacteristic *characteristic in service.characteristics)
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]])
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
if (error)
NSLog(@"Error");
return;
NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
if ([stringFromData isEqualToString:@"EOM"])
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
[_centralManager cancelPeripheralConnection:peripheral];
//[_data appendData:characteristic.value];
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]])
return;
if (characteristic.isNotifying)
NSLog(@"Notification began on %@", characteristic);
else
// Notification has stopped
[_centralManager cancelPeripheralConnection:peripheral];
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
_foundPeripherals = nil;
[_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@ CBCentralManagerScanOptionAllowDuplicatesKey : @YES ];
- (void)cleanup
// See if we are subscribed to a characteristic on the peripheral
if (_currentperipheral.services != nil)
for (CBService *service in _currentperipheral.services)
if (service.characteristics != nil)
for (CBCharacteristic *characteristic in service.characteristics)
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]])
if (characteristic.isNotifying)
[_currentperipheral setNotifyValue:NO forCharacteristic:characteristic];
return;
[_centralManager cancelPeripheralConnection:_currentperipheral];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier" forIndexPath:indexPath];
if (cell == nil)
cell = [ [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"reuseIdentifier"] ;
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.textLabel.text = [_foundPeripherals objectAtIndex:indexPath.row];
// Configure the cell...
return cell;
【问题讨论】:
【参考方案1】:这里有很多代码,但总体看起来还可以。然而,有两件事很突出。您的 numberOfSectionsInTableView
返回 0 - 因此您的表格中将没有内容。你应该有 -
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
// Return the number of sections.
return 1;
我建议您将 CBPeripheral 存储在您的数据数组中。
此外,一旦你发现了一个外围设备并将其添加到你的数组中,你应该通知 table view 数据源已经更新(这个代码假设你有属性 tableView
包含对你的 tableview 的引用) -
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
NSLog(@"Discovered %@ at %@", peripheral.name, RSSI);
if (![_foundPeripherals containsObject:peripheral])
[_foundPeripherals addObject:myDevice ] ;
[self.tableView reloadData]; // Tell the tableview that the data source has changed
那么你的cellForRowAtIndexPath
就变成了-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier" forIndexPath:indexPath];
if (cell == nil)
cell = [ [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"reuseIdentifier"] ;
cell.selectionStyle = UITableViewCellSelectionStyleGray;
CBPeripheral *peripheral=[_foundPeripherals objectAtIndex:indexPath.row];
cell.textLabel.text = peripheral.name;
// Configure the cell...
return cell;
选择表格行时连接外围设备 -
- (void)tableView: (UITableView *)tableView
didSelectRowAtIndexPath: (NSIndexPath *)indexPath
[self performSegueWithIdentifier:@"connectSegue" sender:[_foundPeripherals objectAtIndex:indexPath.row]]; // This is a segue to your BTSentCommandViewController
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
BTSentCommandViewController* sliderVC=( BTSentCommandViewController *)segue.destinationViewController;
sliderVC.centralManager=_centralManager;
sliderVC.periperhal=_sender;
在您的BTSentCommandViewController
中,您可以连接到外围设备。您还应该将BTSentCommandViewController
实例设置为外围设备委托并在那里实现所有CBPeripheralDelegate
方法
【讨论】:
我使用了 LightBlue,因此检查了几个设备。至于我的应用程序,他们甚至都没有遵循你的工作。 我必须通过prepareForSegue调用方法连接蓝牙的哪一部分? 我会在 prepareForSegue 中将 CBPeripheral 传递给您的目标视图控制器,然后在viewWillAppear
中连接它 - 但您可能应该从视图控制器中删除所有 CoreBluetooth 内容并将其放在单独的类 - 它会让你的视图控制器实现更干净以上是关于IOS 蓝牙 LE 扫描设备未添加到 uitableview的主要内容,如果未能解决你的问题,请参考以下文章