首先实现扫描功能,
1: 定义扫描接口,定义接口主要是降低耦合(实现该接口可以很轻松的重构扫描模块)
1:ScanBuilder 扫描构建器,描述创建扫描类需要的参数,以及返回对应的扫描器实例。
2:只有一个函数 scan ,返回值为 Observable
protocol BluetoothScanable {
var scanInfo: (scanPrefix: [String], services: [CBUUID]) { get }
var centralManager : CBCentralManager { get }
typealias Input = (
centralManager: CBCentralManager,
scanInfo: (scanPrefix: [String], services: [CBUUID])
)
typealias ScanBuilder = (BluetoothScanable.Input) -> BluetoothScanable
func scan(duration: Int) -> Observable<(state: ScanState, response : [ScanResponse]?)>
}
public class ScanResponse {
var peripheral: CBPeripheral
var advertisementData: [String : Any]?
var rssi: NSNumber
init(peripheral: CBPeripheral,
advertisementData: [String : Any]? = nil,
rssi: NSNumber = NSNumber.init(value: 0)) {
self.peripheral = peripheral
self.advertisementData = advertisementData
self.rssi = rssi
}
}复制代码
复制代码
2: 扫描实现类
实现 BluetoothScanable 接口, 扫描的结果通过 信号的方式回传。
class BluetoothScan: BluetoothScanable {
var scanInfo: (scanPrefix: [String], services: [CBUUID])
var centralManager: CBCentralManager
init(centralManager: CBCentralManager, scanInfo: (scanPrefix: [String], services: [CBUUID])) {
self.centralManager = centralManager
self.scanInfo = scanInfo
}
func scan(duration: Int) -> Observable<(state: ScanState, response : [ScanResponse]?)> {
// 返回 Observable
return Observable<(state: ScanState, response : [ScanResponse]?)>.create { [centralManager, scanInfo] (subscriber) -> Disposable in
if centralManager.state == .poweredOn {
// 获取已连接
var connected = centralManager.retrieveConnectedPeripherals(withServices: scanInfo.services)
// 扫描前缀过滤
connected = connected.filter({ p in
return (scanInfo.scanPrefix.filter({(p.name?.hasPrefix($0) ?? false)}).count) > 0
})
// 转为 ScanResponse 对象
let scanResponses = connected.map({ ScanResponse(peripheral: $0) })
if scanResponses.count > 0 {
subscriber.onNext((state: .nomal, response: scanResponses))
}
// 订阅扫描结果 ,接收信号发送过来的扫描结果
_ = centralManager.rx.didDiscoverPeripheral.filter({ p in
return (scanInfo.scanPrefix.filter({
(p.peripheral.name?.hasPrefix($0) ?? false)
}).count) > 0
}).subscribe(onNext: { (response) in
//信号发送给订阅者
subscriber.onNext((state: .nomal, response: [response]))
})
// 开始扫描
if UIApplication.shared.applicationState == .background {
centralManager.scanForPeripherals(withServices: scanInfo.services , options: nil)
} else {
centralManager.scanForPeripherals(withServices: nil, options: nil)
}
// 指定时间停止扫描
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(duration)) {
//结束发送给订阅者
centralManager.stopScan()
subscriber.onNext((state: .end, response: []))
subscriber.onCompleted()
}
} else {
subscriber.onError(ScanError.error(messae: "Bluetooth state error"))
}
return Disposables.create()
}
}
}复制代码
复制代码
3 : 扫描结果订阅的实现
CBCentralManager 扩展rx属性 , 直接返回 RxCBCentralManagerDelegateProxy 对象中的PublishSubject 属性。 外部订阅 rx 属性即可收到扫描结果信号。
extension Reactive where Base: CBCentralManager {
public var delegate: DelegateProxy {
return RxCBCentralManagerDelegateProxy.proxy(for: base)
}
public var didUpdateState: Observable {
return RxCBCentralManagerDelegateProxy.proxy(for: base)
.didUpdateStateSubject
.asObservable()
}
public var didDiscoverPeripheral: Observable {
return RxCBCentralManagerDelegateProxy.proxy(for: base)
.didDiscoverPeripheralSubject
.asObservable()
}
public var didConectPeripheral: Observable {
return RxCBCentralManagerDelegateProxy.proxy(for: base)
.didConnectPeripheralSubject
.asObservable()
}
public var didFailToConnectPeripheral: Observable {
return RxCBCentralManagerDelegateProxy.proxy(for: base)
.didFailToConnectPeripheralSubject
.asObservable()
}
public var didDisconnectPeripheral: Observable {
return RxCBCentralManagerDelegateProxy.proxy(for: base)
.didDisconnectPeripheralSubject
.asObservable()
}
}
class RxCBCentralManagerDelegateProxy: DelegateProxy, DelegateProxyType, CBCentralManagerDelegate {
// 系统代理会掉时,用于发送信号, 任何想知道扫描结果的都可以订阅
var didUpdateStateSubject = PublishSubject()
var didDiscoverPeripheralSubject = PublishSubject()
var didConnectPeripheralSubject = PublishSubject()
var didFailToConnectPeripheralSubject = PublishSubject()
var didDisconnectPeripheralSubject = PublishSubject()
init(_ centerManager: CBCentralManager) {
super.init(parentObject: centerManager, delegateProxy: RxCBCentralManagerDelegateProxy.self)
}
/// 注册代理的实现为 RxCBCentralManagerDelegateProxy 实例
static func registerKnownImplementations() {
self.register {
RxCBCentralManagerDelegateProxy($0)
}
}
static func currentDelegate(for object: CBCentralManager) -> CBCentralManagerDelegate? {
return object.delegate
}
static func setCurrentDelegate(_ delegate: CBCentralManagerDelegate?, to object: CBCentralManager) {
object.delegate = delegate
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
_forwardToDelegate?.centralManagerDidUpdateState(central)
/// 当代理回调 蓝牙状态发生变化 发送信号给订阅者
didUpdateStateSubject.onNext(central.state)
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
didDiscoverPeripheralSubject.onNext(ScanResponse(peripheral: peripheral, advertisementData: advertisementData, rssi: RSSI))
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
didConnectPeripheralSubject.onNext(ScanResponse(peripheral: peripheral))
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
didFailToConnectPeripheralSubject.onNext(ScanResponse(peripheral: peripheral))
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
didDisconnectPeripheralSubject.onNext(ScanResponse(peripheral: peripheral))
}
}复制代码
复制代码
4 : 具体使用
1: 在 didFinishLaunchingWithOptions 中 先配置 BleFacade (初始化蓝牙)提供要连接的设备名或扫描的前缀以及服务特征,配置BleFacade 中使用的设备扫描器 和 设备连接器。 所有蓝牙操作都通过BleFacade类执行。
// 连接 的具体实现类, 扫描器的Builer 会传入 centralManager 和 scanInfo
let scanBuilder: BluetoothScanable.ScanBuilder = {
BluetoothScan(centralManager: $0.centralManager, scanInfo: $0.scanInfo)
}
// 连接 的具体实现类, 扫描器的Builer 会传入 centralManager 和 scanInfo 以及 scaner
let connectBuilder: BluetoothConnectable.ConnectBuilder = {
BluetoothConnect(
centralManager: $0.centralManager,
connectInfo: $0.connectInfo,
scaner: $0.scaner
)
}
// 扫描 和 连接 的配置
let services = [CBUUID.init(string: "service uuid1"), CBUUID.init(string: "service uuid2")]
let config = BleDeviceConfig("DeviceName", ["DeviceNamePrefix"], services)
BleFacade.shared.config(config, scanBuilder, connectBuilder)复制代码
复制代码
// 在需要扫描的地方 执行扫描操作即可
func clicnScanBtn(_ sender: Any) {
BleFacade.shared.scaner.scan(duration: 3)
.subscribe(onNext: { (state, response) in
if state == .nomal {
response?.filter({ $0.peripheral.name != nil }).forEach({ (res) in
print("per name: (String(describing: res.peripheral.name))")
})
} else if (state == .end) {
print("扫描结束")
}
}, onError: { error in
print("(error)")
}).disposed(by: bag)
}复制代码
复制代码
结束语;如对RxSwift感兴趣的可以;563513413,不管你是大牛还是小白都欢迎入驻。大家可以互相交流学习................