簡體   English   中英

檢測 Apple Pencil 是否連接到 iPad Pro

[英]Detect whether Apple Pencil is connected to an iPad Pro

是否有 API 可以讓您確定 Apple Pencil 是否連接到 iPad Pro? 查看 9.1 SDK,我沒有看到任何直接執行此操作的內容。 或者這可以使用藍牙 API 來完成。

我找不到有關 Apple Pencil 藍牙實現的任何實際文檔(我認為不存在任何文檔),但以下代碼適用於我™。

它會檢查宣傳自己支持“設備信息”服務的已連接設備,然后檢查這些設備中是否有任何名稱為“Apple Pencil”。

鉛筆檢測器.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

在實踐中,以下更簡單的同步代碼在檢查連接的設備之前不等待中央管理器開機,在我的測試中似乎也能正常工作。 但是,文檔指出,在狀態更新為CBCentralManagerStatePoweredOn之前,您不應在管理器上調用任何方法,因此較長的代碼可能更安全。

你喜歡的任何地方

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)發起連接時才被調用功能(是的,閱讀文檔有幫助:])。

由於我們沒有通過用戶將設備連接到設備的回調(就像 Apple Pencil 的情況一樣 - 順便說一句,我很想證明這是錯誤的),我不得不在這里使用計時器。

這是它的工作原理:

當您初始化ApplePencilReachability會設置一個計時器, ApplePencilReachability檢查鉛筆的可用性。 如果找到鉛筆,計時器就會失效,如果藍牙關閉,它也會失效。 當它再次打開時,會創建一個新的計時器。

我不是特別自豪,但它有效:-)

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

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM