提示:
1,本篇文章是本人凭4年经验创作,如果有什么不正确的地方,请您提出,我改正。
2,文章中所涉及到的思想,在我的开源库中都有体现。喜欢的话给个start,如果您在使用过程中遇到任何问题,我们可以一对一进行沟通。
从上篇文章中,我们应该对蓝牙开发有了个大概的了解,接下来我会对蓝牙框架中的每一个类,从苹果官方文档出发来详细讲解。
目录:
//对象类
CBPeer : NSObject
CBCentral: CBPeer
CBPeripheral : CBPeer
//管理类
CBManager : NSObject
CBPeripheralManager : CBManager
CBCentralManager: CBManager
//属性类
CBAttribute: NSObject
CBCharacteristic : CBAttribute
CBDescriptor : CBAttribute
CBService : CBAttribute
//其他
CBATTRequest: NSObject
CBUUID: NSObject
对象类
CBPeer: NSObject
介绍:
它是主设备,从设备的抽象基类,用于定义表示设备的对象的常见行为。
它是CBCentral ,CBPeripheral的基类,所以这两个类都具有identifier属性。也就是设备的唯一标示。
属性:
//设备的唯一ID。(相当于UUID)
@property(readonly, nonatomic) NSUUID *identifier
方法:
无
CBCentral: CBPeer
介绍:
表示已连接到在本地设备上实现外设角色的应用程序的远程中央设备。
也就是说,当您使用CBPeripheralManager类实现外设角色时,连接到本地外设的中心将表示为CBCentral对象。
属性:
//所能接受数据的最大长度。
@property(readonly, nonatomic) NSUInteger maximumUpdateValueLength;
方法:
无
CBPeripheral : CBPeer
介绍:
代表一个发现广播或当前连接到的远程外围设备。
在这个类上发现服务,然后再在服务的特征上进行数据交互。
(通常不用自己创建,系统发现设备就会主动创建它,并返回)
属性:
//设备的代理,接受的外部事件都将在代理方法中返回
@property(weak, nonatomic, nullable) id<CBPeripheralDelegate> delegate;
//设备的名称
@property(retain, readonly, nullable) NSString *name;
//设备信号的强度。
@property(retain, readonly, nullable) NSNumber *RSSI ;
//设备当前状态 (已断开连接,正在连接,已连接,正在断开连接)
@property(readonly) CBPeripheralState state;
//已发现的外设上的服务列表。
//需发现服务(- discoverServices: 和 - discoverIncludedServices:forService:)后才会有值
@property(retain, readonly, nullable) NSArray<CBService *> *services;
方法:
//当设备连接之后,读取设备的信号强度。
- (void)readRSSI;
//当rssi发生变化后会调用如下方法
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(nullable NSError *)error ;//已废弃
- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error ;
//发现外设上所有的可用服务。
* serviceUUIDs : 表示要发现的服务的对象的列表。
- (void)discoverServices:(nullable NSArray<CBUUID *> *)serviceUUIDs;
//当设备上发现需要的服务的时候,会触发如下方法。
发现的服务将会在设备的services属性中。
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error;
//发现指定的服务包含的服务。
*includedServiceUUIDs: 表示要发现的服务的对象的列表。
*service: 所在的服务
- (void)discoverIncludedServices:(nullable NSArray<CBUUID *> *)includedServiceUUIDs forService:(CBService *)service;
//当调用上面的方法,会触以下方法。
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(nullable NSError *)error;
//表示需要发现服务上面的特征属性
- (void)discoverCharacteristics:(nullable NSArray<CBUUID *> *)characteristicUUIDs forService:(CBService *)service;
//如果发现特征,会触发如下方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error;
//读特征上的数据 并非所有特性都保证具有可读值。 可以通过访问CBCharacteristicProperties枚举的相关属性来确定特征值是否可读,
- (void)readValueForCharacteristic:(CBCharacteristic *)characteristic;
//当特征上的值发生改变时,会触发这个方法。(1,监听特征,2,读特征)。改变的值在characteristic中的value值。
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
//可以以单个写入类型发送到特性的最大数据量(以字节为单位)。
//type:写数据的方式
- (NSUInteger)maximumWriteValueLengthForType:(CBCharacteristicWriteType)type;
//data:需要写入的数据
//characteristic:所在的特征
//type:是否需要回执 如果指定为CBCharacteristicWriteWithoutResponse,那么数据的传送是尽力而为的,不会保证必须到达。
- (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type;
//数据写入后的结果回调,会触发这个方法。需要检查error中的值。
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
//指示您是否希望在特征的值更改时接收通知或指示。
- (void)setNotifyValue:(BOOL)enabled forCharacteristic:(CBCharacteristic *)characteristic;
//当调用上面的方法,会触发下面的方法来告诉设置通知开始是否成功。如果值改变后的通知不在这个方法中返回。
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
//发现特征上的描述。如果特征的描述符被成功发现,您可以通过特征描述符属性来访问它们。
- (void)discoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic;
//发现描述后会触发这个方法。所有的描述数组值会在characteristic属性descriptors中给出。
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
//读取特征描述符的值
- (void)readValueForDescriptor:(CBDescriptor *)descriptor;
//调用上面方法读取描述值,如果成功检索到特征描述符的值,则可以通过特征描述符的value属性来访问它。如果失败,会在error中提现。
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error;
//往描述上写数据
- (void)writeValue:(NSData *)data forDescriptor:(CBDescriptor *)descriptor;
//写描述值后会触发方法
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error;
//当设备的名称改变的时候会调用这个方法
- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral ;
//当设备的服务被改变的时候,回调这个方法。
//此时设备指定的服务,已无效。需要重新调用发现服务方法寻找服务。
- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices ;
管理类
CBManager : NSObject
介绍:
核心蓝牙管理器对象(主设备和从设备)的抽象基类。
他是CBPeripheralManager, CBCentralManager的基类,所以这两个类都具有state这个属性。
属性:
//当前manager的状态,初始值为CBManagerStateUnknown ,更新由必需的委托方法 managerDidUpdateState:提供。
@property(nonatomic, assign, readonly) CBManagerState state;
方法:
无
CBPeripheralManager: CBManager
介绍:
类是Peripheral的管理者对象。其主要功能是允许您管理GATT数据库中的已发布服务,并向其他设备发布这些服务。
属性:
//将接收外设事件的委托对象。
@property(nonatomic, weak, nullable) id<CBPeripheralManagerDelegate> delegate;
//外设当前是否正在广告数据。
@property(nonatomic, assign, readonly) BOOL isAdvertising;
方法:
//此方法不会提示用户进行访问。 您可以使用它来检测受限访问,只需隐藏UI,而不是提示访问。
当前用于共享数据的授权状态。
+ (CBPeripheralManagerAuthorizationStatus)authorizationStatus ;
//queue:所运行的队列,他派遣在其上发送事件的队列。
//options:指定管理员选项的可选字典。(见底部)
- (instancetype)init;
- (instancetype)initWithDelegate:(nullable id<CBPeripheralManagerDelegate>)delegate
queue:(nullable dispatch_queue_t)queue ;
- (instancetype)initWithDelegate:(nullable id<CBPeripheralManagerDelegate>)delegate
queue:(nullable dispatch_queue_t)queue
options:(nullable NSDictionary<NSString *, id> *)options ;
//开始广播数据
- (void)startAdvertising:(nullable NSDictionary<NSString *, id> *)advertisementData;
//开始广播后会触发如下方法。
如果无法启动广播,则会在error参数中详细说明原因。
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(nullable NSError *)error;
//停止广播
- (void)stopAdvertising;
// 将现有连接的期望连接延迟设置为中央设备。 连接延迟更改不能保证,所以延迟可能会有所不同。 如果未设置期望的延迟,则将使用在连接建立时由中心设备选择的延迟。 通常,不需要更改延迟。
// latency 所需的连接延迟。
- (void)setDesiredConnectionLatency:(CBPeripheralManagerConnectionLatency)latency forCentral:(CBCentral *)central;
//向设备中添加一个服务及其关联特征。 如果服务包含包含的服务,则必须首先发布。
- (void)addService:(CBMutableService *)service;
//添加服务成功,会触发下面方法。
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(nullable NSError *)error;
//从服务列表红移除一个已经发布的服务,如果这个服务包含了其他服务,那么必须先移除前者
- (void)removeService:(CBMutableService *)service;
//移除所有已经发布的所有服务service
- (void)removeAllServices;
//响应一个从central传过来读或者写请求
- (void)respondToRequest:(CBATTRequest *)request withResult:(CBATTError)result;
//当外设接收到具有动态值的特性的ATT请求时,将调用此方法。
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request;
//当外设接收到具有动态值的一个或多个特性的ATT请求或命令时,将调用此方法。
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests;
//为订阅了peripheral的central更新characteristic里面的值。
- (BOOL)updateValue:(NSData *)value forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:(nullable NSArray<CBCentral *> *)centrals;
//调用updateValue之后调用此方法:forCharacteristic:onSubscribedCentrals:,当外设再次准备好发送特征值更新。
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral;
//当central配置特征通知或指示时,将调用此方法。 当特征值发生变化时,应将其用作开始发送更新的提示。
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic;
//当中心从特征中删除通知/指示时,将调用此方法。
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic;
//外围经理的状态已经改变。
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral;
//对于选择加入状态保存和恢复的应用程序,当您的应用程序重新启动到后台完成某些蓝牙相关任务时,这是第一个调用的方法。 使用此方法将应用程序的状态与蓝牙系统的状态同步。
//dict 包含系统在应用程序终止时保留的有关外设的信息的字典。
- (void)peripheralManager:(CBPeripheralManager *)peripheral willRestoreState:(NSDictionary<NSString *, id> *)dict;
CBCentralManager: CBManager
介绍:
相当于主设备,用来管理发现或连接的远程外围设备。包括扫描,发现和连接到广告外设。
在使用其中的方法的时候,蓝牙必须是打开状态。
属性:
//接收中心事件的委托对象。
@property(nonatomic, weak, nullable) id<CBCentralManagerDelegate> delegate;
//中央是否正在扫描。
@property(nonatomic, assign, readonly) BOOL isScanning ;
方法:
//初始化方法
//queue 操作所运行的线程,如果不传就会在主线程上运行。
//options 指定CentralManager选项字典。
CBCentralManagerOptionShowPowerAlertKey (对应的BOOL值,当设为YES时,表示CentralManager初始化时,如果蓝牙没有打开,将弹出Alert提示框)
CBCentralManagerOptionRestoreIdentifierKey(唯一标识的字符串,用于蓝牙进程被杀掉恢复连接时用的。)
- (instancetype)init;
- (instancetype)initWithDelegate:(nullable id<CBCentralManagerDelegate>)delegate
queue:(nullable dispatch_queue_t)queue;
- (instancetype)initWithDelegate:(nullable id<CBCentralManagerDelegate>)delegate
queue:(nullable dispatch_queue_t)queue
options:(nullable NSDictionary<NSString *, id> *)options ;
//如果主设备的蓝牙状态发生改变,会触发这个方法。
此方法必须实现,比如用户关闭系统蓝牙,就应该处理这个事件。
- (void)centralManagerDidUpdateState:(CBCentralManager *)central;
//在蓝牙于后台被杀掉时,重连之后会首先调用此方法,可以获取蓝牙恢复时的各种状态
- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary<NSString *, id> *)dict;
//该方法整理出所有连接到中央设备(比如iphone)的外设。(根据UUID找到所有匹配的蓝牙对象)
返回一个数组(该数组包含了所有app连接的外设列表)
- (NSArray<CBPeripheral *> *)retrievePeripheralsWithIdentifiers:(NSArray<NSUUID *> *)identifiers ;
//从连接的设备(可能有多个app连接不同的蓝牙设备)中,根据服务列表,返回这些服务的数组(也就是找到我们指定的服务设备,整理到一个数组中返回)
此套件可能包括由其他应用程序连接的外围设备,但是还是需要连接后才能使用
- (NSArray<CBPeripheral *> *)retrieveConnectedPeripheralsWithServices:(NSArray<CBUUID *> *)serviceUUIDs ;
//扫描外部设备
serviceUUIDs:扫描外设必须包含的服务列表(如果为空,将全部扫描)
options:扫描时所遵循的规则
*CBCentralManagerScanOptionAllowDuplicatesKey 默认为NO,过滤功能是否启用,每次寻找都会合并相同的peripheral。如果设备YES的话每次都能接受到来自peripherals的广播包数据。
*CBCentralManagerScanOptionSolicitedServiceUUIDsKey 想要扫描的服务的UUID,以一个数组的形式存在。扫描的时候只会扫描到包含这些UUID的设备。
- (void)scanForPeripheralsWithServices:(nullable NSArray<CBUUID *> *)serviceUUIDs options:(nullable NSDictionary<NSString *, id> *)options;
//上面的方法调用,发现一个设备,会回到下面的方法。
//advertisementData:从设备所包含的广播数据。
//RSSI:设备的信号强度
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI;
//停止扫描外设
- (void)stopScan;
//连接一个设备
options:连接时所尊重的规则
*CBConnectPeripheralOptionNotifyOnConnectionKey 默认为NO,APP被挂起时,这时如果连接到peripheral时,是否要给APP一个提示框。
*CBConnectPeripheralOptionNotifyOnDisconnectionKey 默认为NO,APP被挂起时,恰好在这个时候断开连接,要不要给APP一个断开提示。
*CBConnectPeripheralOptionNotifyOnNotificationKey 默认为NO,APP被挂起时,是否接受到所有的来自peripheral的包都要弹出提示框。
- (void)connectPeripheral:(CBPeripheral *)peripheral options:(nullable NSDictionary<NSString *, id> *)options;
//上面的连接设备方法,只有两种可能,一种是成功,一种是不成功。 所以以下两个方法有且只有一个调用。
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;
*由于连接尝试不超时,连接失败是非典型的,通常表示暂时的问题。
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;
//取消与外部设备的连接
- (void)cancelPeripheralConnection:(CBPeripheral *)peripheral;
//主设备与从设备失去连接,将会调用如下方法。这个方法必须处理,应为很有可能是由于外部原因(设备电量低,设备故障)等失去连接。这时需要提示用户。
*如果是调用上面方法主动断开连接,error会为空。
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;
属性类
CBAttribute: NSObject
介绍:
一个抽象基类,它定义了表示由外设提供的服务方面的对象集合的共同行为。
CBService,CBCharacteristic,CBDescriptor的基类,所以这仨个类都具有UUID这个属性。
属性:
//唯一ID
@property(readonly, nonatomic) CBUUID *UUID;
方法:
无
CBService : CBAttribute
介绍:
此类及其子类CBMutableService表示外设的服务,用于完成设备(或该设备的部分)的功能或功能的数据和相关行为的集合,表示远程外围设备的服务。
服务是主要的或次要的,可能包含许多特征或包含的服务(对其他服务的引用)。
属性:
//服务所属的设备
@property(assign, readonly, nonatomic) CBPeripheral *peripheral;
//是否是主服务
@property(readonly, nonatomic) BOOL isPrimary;
//目前在该服务中已发现的包含CBServices的列表。
@property(retain, readonly, nullable) NSArray<CBService *> *includedServices;
//此服务中所有被发现的特征列表。
@property(retain, readonly, nullable) NSArray<CBCharacteristic *> *characteristics;
方法:
无
CBCharacteristic : CBAttribute
介绍:
此类及子类CBMutableCharacteristic表示有关外设服务的更多信息,表示远程外设服务的特性。
特征包含单个值和描述该值的任意数量的描述符。 特性的属性决定了如何使用特征值,以及如何访问描述符。
属性:
//这个特征所在的服务
@property(assign, readonly, nonatomic) CBService *service;
//这个特征所拥有的属性
@property(readonly, nonatomic) CBCharacteristicProperties properties;
//特征上的值
@property(retain, readonly, nullable) NSData *value;
//特征上所拥有的描述
@property(retain, readonly, nullable) NSArray<CBDescriptor *> *descriptors;
//该特征是否被广播。
@property(readonly) BOOL isBroadcasted ;
//通知是否已开启
@property(readonly) BOOL isNotifying;
方法:
无
CBDescriptor : CBAttribute
介绍:
描述及其子类CBMutableDescriptor表示外设特性的描述,提供有关特征值的进一步信息。
特征描述符还指示当特征值变化时,是否在服务器(外围设备)上配置特征值来指示或通知客户端(中央)。
属性:
//这个描述所属的特征
@property(assign, readonly, nonatomic) CBCharacteristic *characteristic;
//描述上的值
@property(retain, readonly, nullable) id value;
方法:
无
其他
CBATTRequest: NSObject
介绍
“表示来自远程中央设备(由CBCentral对象表示)的属性协议(ATT)读取和写入请求。
远程中心使用这些ATT请求在本地外设(由CBPeripheralManager对象表示)上读写特征值。
另一方面,本地外设使用CBATTRequest对象的属性可以使用CBPeripheralManager类的respondToRequest:withResult:method来适当地响应读写请求。
服务对象是外设向中心设备提供的相关数据服务,获取到相应服务后,中心设备可以进行读写请求。
属性:
//发起请求的中心。
@property(readonly, nonatomic) CBCentral *central;
//其值将被读取或写入的特征。
@property(readonly, nonatomic) CBCharacteristic *characteristic;
//读取或写入的第一个字节的从零开始的索引。
@property(readonly, nonatomic) NSUInteger offset;
//写入或读取的数据
@property(readwrite, copy, nullable) NSData *value;
方法:
无
CBUUID: NSObject
介绍:
它代表一个属性唯一的ID,是由16、32、128位数字组成。
一般用在外设所提供的服务,特征,描述上面。
属性:
//uuid上的数据
@property(nonatomic, readonly) NSData *data;
//uuid所表示的字符串
@property(nonatomic, readonly) NSString *UUIDString
方法:
全为初始化方法
//通过字符串方式创建一个UUID
+ (CBUUID *)UUIDWithString:(NSString *)theString;
//通过data创建一个UUID
+ (CBUUID *)UUIDWithData:(NSData *)theData;
//通过CFUUIDRef对象创建一个UUID
+ (CBUUID *)UUIDWithCFUUID:(CFUUIDRef)theUUID;
//通过NSUUID创建一个UUID
+ (CBUUID *)UUIDWithNSUUID:(NSUUID *)theUUID ;
CBAdvertisementData.h
这是一个常量类,这里面定义的常量都是从设备广播出来的数据的键值对。
当主设备发现从设备相应代理里面所包含的广播数据 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
CBAdvertisementDataLocalNameKey 设备的广播名
CBAdvertisementDataTxPowerLevelKey 外设的发送功率
CBAdvertisementDataServiceDataKey 特定服务的分发数据
CBAdvertisementDataServiceUUIDsKey 需要公布的服务的`UUID`数组
CBAdvertisementDataManufacturerDataKey 设备的生产厂家
CBAdvertisementDataOverflowServiceUUIDsKey 附加服务的UUID数组
CBAdvertisementDataIsConnectable 表示是否可被连接
CBAdvertisementDataSolicitedServiceUUIDsKey 一个代表着一个或多个服务的`UUID`
CBPeripheralManagerOptionShowPowerAlertKey 对应的值是一个NSNumber类型BOOL值,它标识了在系统peripheral创建在蓝牙关闭的情况下是否应该显示一个警告对话框
CBPeripheralManagerOptionRestoreIdentifierKey 对应的值是一个字典(数组)创建一个CBPeripheralManager的一个实例时从options中取出值去恢复Peripheral的状态
CBPeripheralManagerRestoredStateServicesKey CBMutableService对象的数组,包含系统终止应用程序时发布到本地外设数据库的所有服务。
CBPeripheralManagerRestoredStateAdvertisementDataKey 包含外部管理器在系统终止应用程序时广播的数据的字典。
CBConnectPeripheralOptionNotifyOnDisconnectionKey设置当外设断开连接后是否弹出一个警告
CBConnectPeripheralOptionNotifyOnConnectionKey设置当外设连接后是否弹出一个警告
CBConnectPeripheralOptionNotifyOnNotificationKey设置当外设暂停连接后是否弹出一个警告
note:下一篇文章,我讲着重介绍,我在github上的第三方库, 如您有兴趣,可以先预习下。(希望能给个start🙂)