Is there an API that allows you to determine whether the Apple Pencil is connected to an iPad Pro? Looking over the 9.1 SDK I don\'t see anything that directly does this. Or per
Took me quite a while to figure out that CBCentralManager's centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)
is only called when the connection is initiated via its connect(_ peripheral: CBPeripheral, options: [String : Any]? = nil)
function (yes, reading the docs helps :]).
Since we have no callback for when devices have been connected to the device through the user (as is the case with Apple Pencil - I'd love to be proven wrong on this one btw), I had to resort to using a timer here.
This is how it works:
When you initialize ApplePencilReachability
a timer is setup that checks for the availability of the pencil every second. If a pencil is found the timer gets invalidated, if bluetooth is turned off it also gets invalidated. When it's turned on again a new timer is created.
I am not particularly proud of it but it works :-)
import CoreBluetooth
class ApplePencilReachability: NSObject, CBCentralManagerDelegate {
private let centralManager = CBCentralManager()
var pencilAvailabilityDidChangeClosure: ((_ isAvailable: Bool) -> Void)?
var timer: Timer? {
didSet {
if oldValue !== timer { oldValue?.invalidate() }
}
}
var isPencilAvailable = false {
didSet {
guard oldValue != isPencilAvailable else { return }
pencilAvailabilityDidChangeClosure?(isPencilAvailable)
}
}
override init() {
super.init()
centralManager.delegate = self
centralManagerDidUpdateState(centralManager) // can be powered-on already?
}
deinit { timer?.invalidate() }
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {
[weak self] timer in // break retain-cycle
self?.checkAvailability()
if self == nil { timer.invalidate() }
}
} else {
timer = nil
isPencilAvailable = false
}
}
private func checkAvailability() {
let peripherals = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID(string: "180A")])
let oldPencilAvailability = isPencilAvailable
isPencilAvailable = peripherals.contains(where: { $0.name == "Apple Pencil" })
if isPencilAvailable {
timer = nil // only if you want to stop once detected
}
}
}