检测Apple Pencil是否连接到iPad Pro

有没有API可以让你确定苹果铅笔是否连接到iPad Pro? 查看9.1 SDK我没有看到任何直接做到这一点。 或者也许这可以使用蓝牙API来完成。

我在Apple Pencil的蓝牙实现(我不相信任何存在)上找不到实际的文档,但下面的代码适用于我™。

它会检查连接的设备是否宣称自己支持“设备信息”服务,如果其中任何一个设备名称为“Apple Pencil”。

PencilDetector.h

@import CoreBluetooth @interface PencilDetector : NSObject <CBCentralManagerDelegate> - (instancetype)init; @end 

PencilDetector.m

 #include "PencilDetector.h" @interface PencilDetector () @end @implementation PencilDetector { CBCentralManager* m_centralManager; } - (instancetype)init { self = [super init]; if (self != nil) { // Save a reference to the central manager. Without doing this, we never get // the call to centralManagerDidUpdateState method. m_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil]; } return self; } - (void)centralManagerDidUpdateState:(CBCentralManager *)central { if ([central state] == CBCentralManagerStatePoweredOn) { // Device information UUID NSArray* myArray = [NSArray arrayWithObject:[CBUUID UUIDWithString:@"180A"]]; NSArray* peripherals = [m_centralManager retrieveConnectedPeripheralsWithServices:myArray]; for (CBPeripheral* peripheral in peripherals) { if ([[peripheral name] isEqualToString:@"Apple Pencil"]) { // The Apple pencil is connected } } } } @end 

实际上,在检查连接的设备之前,不等待中央pipe理器通电的以下更简单的同步代码在testing中似乎也起作用。 但是,文档指出,在状态更新为CBCentralManagerStatePoweredOn之前,不应调用pipe理器上的任何方法,因此较长的代码可能更安全。

任何地方你喜欢

 m_centralManager = [[CBCentralManager alloc] initWithDelegate:nil queue:nil options:nil]; // Device information UUID NSArray* myArray = [NSArray arrayWithObject:[CBUUID UUIDWithString:@"180A"]]; NSArray* peripherals = [m_centralManager retrieveConnectedPeripheralsWithServices:myArray]; for (CBPeripheral* peripheral in peripherals) { if ([[peripheral name] isEqualToString:@"Apple Pencil"]) { // The Apple pencil is connected } } 

花了我相当长的时间才发现CBCentralManager的centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)仅在连接通过连接启动时被调用connect(_ peripheral: CBPeripheral, options: [String : Any]? = nil)function(是的,阅读文档有助于:])。

由于我们没有callback设备通过用户连接到设备的时间(例如苹果铅笔 – 我很想在这一个btw上被certificate是错误的),所以我不得不在这里使用计时器。

这是如何工作的:

初始化ApplePencilReachability会设置一个计时器, ApplePencilReachability检查一次铅笔的可用性。 如果发现铅笔定时器失效,如果蓝牙closures,它也会失效。 当它再次打开时,将创build一个新的计时器。

我不是特别自豪,但它的作品:-)

 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 } } }