前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RxSwift 与 BLE 实战——VisualBlue

RxSwift 与 BLE 实战——VisualBlue

作者头像
Sheepy
发布2018-09-10 12:21:50
1.1K0
发布2018-09-10 12:21:50
举报

最近发生了挺多事,也没什么时间更新博客,心中颇有点负疚感。今天就介绍一下前段时间写的一个 demo,主要功能是扫描附近的蓝牙设备,显示相关信息,点击后可以连接设备,并获取更多信息。对 RxSwift 及 BLE 感兴趣的同学可以看看,或有所得。

做过蓝牙相关开发的 iOS 同学们肯定都用过 CoreBluetooth 这个系统框架,使用它的话,几乎所有操作都是通过 delegate 完成的。公司的项目正从 OC 向 Swift 迁移,之前蓝牙部分还全是用 OC 写的,各种 delegate 和 notification 满天飞,看着都头疼。我曾一度想着用 RxSwift 去包装一下 CoreBluetooth,后来发现已经有人做了这件事了,于是就想先写个 demo 看看靠不靠谱。Demo 在这里

UI 非常简陋,只是随便拿 Storyboard 弄了一下,就不细说了。扫描设备的整个流程大致是这样的:

  • 筛选蓝牙状态,将除.PoweredOn之外的状态过滤掉
  • 扫描设备
  • 筛选设备,将已出现过的设备过滤掉
  • 将扫描到的新设备添加到设备列表中
  • 用设备列表构建一个dataSource,并与tableView绑定
  • 将资源添加到disposeBag中,以待统一回收处理

这个过程用 Rx 的风格来写大概是这样的:

func bindDataSource() {
    manager.rx_state
        .filter { $0 == .PoweredOn }
        .take(1)
        .flatMap { _ in self.manager.scanForPeripherals(nil) }
        .filter(isNewPeripheral)
        .map { self.scannedPeripherals.append($0) }
        .map { [SectionModel(model: "Peripheral", items: self.scannedPeripherals)] }
        .bindTo(tableView.rx_itemsWithDataSource(dataSource))
        .addDisposableTo(disposeBag)
}

点击 cell 先会取消选中的高亮效果,然后连接相应的设备,如果连接成功就直接跳转到下一个页面,并用segueperipheral传递过去;否则就弹出一个错误提示:

func configDelegate() {
    tableView.rx_itemSelected
        .subscribeNext { self.tableView.deselectRowAtIndexPath($0, animated: true) }
        .addDisposableTo(disposeBag)

    tableView.rx_modelSelected(ScannedPeripheral.self)
        .asObservable()
        .flatMap { $0.peripheral.connect() }
        .subscribe(handleEvent)
        .addDisposableTo(disposeBag)
}

func handleEvent(event: Event<Peripheral>) {
    switch event {
    case .Next(let peripheral):
        self.performSegueWithIdentifier(SegueId.ShowCharacteristics, sender: peripheral)
    case .Error(let error):
        let alertController = UIAlertController(title: "Connect Failed", message: "Error: \(error)", preferredStyle: .Alert)
        self.presentViewController(alertController, animated: true, completion: nil)
    case .Completed:
        print("Completed")
    }
}

连接了之后主要就是显示该设备所有的characteristics,它们分别属于哪个service,有哪些properties什么的。

流程:

  • 发现服务
  • 发现特征(对应了硬件那边所谓的通道……)
  • 构建dataSource,并与tableView绑定

核心代码:

func bindDataSource() {
    guard let peripheral = peripheral else { return }
    peripheral.discoverServices(nil)
        .flatMap(discoverCharacteristics)
        .map { [SectionModel(model: "Characteristic", items: $0)] }
        .bindTo(tableView.rx_itemsWithDataSource(dataSource))
        .addDisposableTo(disposeBag)
}

func discoverCharacteristics(services: [Service]) -> Observable<[Characteristic]> {
    return services
        .map { $0.discoverCharacteristics(nil) }
        .toObservable()
        .switchLatest()
}

有空的话我可能还会为这个 demo 再加些内容,譬如加上监听蓝牙通道、向设备发送数据等功能,或许还会优化一下 UI 和交互,譬如连接蓝牙的时候加个进度动画什么的。大家要是有兴趣的话也欢迎提交 P-R。Have fun ^ ^

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.07.20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档