BluetoothStateManager.swift 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import CoreBluetooth
  2. import LoopKit
  3. import LoopKitUI
  4. import Swinject
  5. protocol BluetoothStateManager: BluetoothProvider {}
  6. public class BaseBluetoothStateManager: NSObject, BluetoothStateManager, Injectable {
  7. private var completion: ((BluetoothAuthorization) -> Void)?
  8. private var centralManager: CBCentralManager?
  9. private var bluetoothObservers = WeakSynchronizedSet<BluetoothObserver>()
  10. init(resolver: Resolver) {
  11. super.init()
  12. injectServices(resolver)
  13. if bluetoothAuthorization != .notDetermined {
  14. centralManager = CBCentralManager(delegate: self, queue: nil)
  15. }
  16. }
  17. public var bluetoothAuthorization: BluetoothAuthorization {
  18. BluetoothAuthorization(CBCentralManager.authorization)
  19. }
  20. public var bluetoothState: BluetoothState {
  21. guard let centralManager = centralManager else {
  22. return .unknown
  23. }
  24. return BluetoothState(centralManager.state)
  25. }
  26. public func authorizeBluetooth(_ completion: @escaping (BluetoothAuthorization) -> Void) {
  27. guard centralManager == nil else {
  28. completion(bluetoothAuthorization)
  29. return
  30. }
  31. self.completion = completion
  32. centralManager = CBCentralManager(delegate: self, queue: nil)
  33. }
  34. public func addBluetoothObserver(_ observer: BluetoothObserver, queue: DispatchQueue = .main) {
  35. bluetoothObservers.insert(observer, queue: queue)
  36. }
  37. public func removeBluetoothObserver(_ observer: BluetoothObserver) {
  38. bluetoothObservers.removeElement(observer)
  39. }
  40. }
  41. // MARK: - CBCentralManagerDelegate
  42. extension BaseBluetoothStateManager: CBCentralManagerDelegate {
  43. public func centralManagerDidUpdateState(_ central: CBCentralManager) {
  44. if let completion = completion {
  45. completion(bluetoothAuthorization)
  46. self.completion = nil
  47. }
  48. bluetoothObservers.forEach { $0.bluetoothDidUpdateState(BluetoothState(central.state)) }
  49. }
  50. }
  51. // MARK: - BluetoothAuthorization
  52. private extension BluetoothAuthorization {
  53. init(_ authorization: CBManagerAuthorization) {
  54. switch authorization {
  55. case .notDetermined:
  56. self = .notDetermined
  57. case .restricted:
  58. self = .restricted
  59. case .denied:
  60. self = .denied
  61. case .allowedAlways:
  62. self = .authorized
  63. @unknown default:
  64. self = .notDetermined
  65. }
  66. }
  67. }
  68. // MARK: - BluetoothState
  69. private extension BluetoothState {
  70. init(_ state: CBManagerState) {
  71. switch state {
  72. case .unknown:
  73. self = .unknown
  74. case .resetting:
  75. self = .resetting
  76. case .unsupported:
  77. #if IOS_SIMULATOR
  78. self = .poweredOn // Simulator reports unsupported, but pretend it is powered on
  79. #else
  80. self = .unsupported
  81. #endif
  82. case .unauthorized:
  83. self = .unauthorized
  84. case .poweredOff:
  85. self = .poweredOff
  86. case .poweredOn:
  87. self = .poweredOn
  88. @unknown default:
  89. self = .unknown
  90. }
  91. }
  92. }