You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS开发:如何监听iOS设备接入或断开Mac的通知

实现方案

你可以通过IOKit框架监听USB设备的插拔事件,过滤Apple Vendor ID即可实现iPhone、iPad的接入/断开检测,具体实现步骤如下:

1. 项目配置

引入IOKit.framework到项目中,若应用开启了沙盒,需要在签名与权限配置中开启USB访问权限。

2. 导入依赖头文件

#import <IOKit/IOKitLib.h>
#import <IOKit/usb/IOUSBLib.h>

3. 核心实现代码

先声明全局变量存储监听上下文:

// 全局通知端口
IONotificationPortRef gNotifyPort;
// 设备接入迭代器
io_iterator_t gAddedIter;
// 设备断开迭代器
io_iterator_t gRemovedIter;

实现设备监听启动方法:

- (void)startMonitoringIOSDevices {
    // 创建USB设备匹配字典
    CFMutableDictionaryRef matchDict = IOServiceMatching(kIOUSBDeviceClassName);
    if (!matchDict) return;
    
    // 过滤Apple设备的固定Vendor ID: 0x05AC
    int appleVID = 0x05AC;
    CFNumberRef vidRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &appleVID);
    CFDictionarySetValue(matchDict, CFSTR(kUSBVendorID), vidRef);
    CFRelease(vidRef);
    
    // 初始化通知端口并加入当前RunLoop
    gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(gNotifyPort), kCFRunLoopDefaultMode);
    
    // 注册设备接入回调
    IOServiceAddMatchingNotification(gNotifyPort, kIOFirstMatchNotification, matchDict, DeviceAddedCallback, (__bridge void *)self, &gAddedIter);
    // 手动调用一次处理已连接的设备
    DeviceAddedCallback((__bridge void *)self, gAddedIter);
    
    // 注册设备断开回调,需重新创建匹配字典
    CFMutableDictionaryRef removeMatchDict = IOServiceMatching(kIOUSBDeviceClassName);
    CFNumberRef removeVidRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &appleVID);
    CFDictionarySetValue(removeMatchDict, CFSTR(kUSBVendorID), removeVidRef);
    CFRelease(removeVidRef);
    
    IOServiceAddMatchingNotification(gNotifyPort, kIOTerminatedNotification, removeMatchDict, DeviceRemovedCallback, (__bridge void *)self, &gRemovedIter);
    DeviceRemovedCallback((__bridge void *)self, gRemovedIter);
}

实现设备插拔回调函数:

// 设备接入回调
void DeviceAddedCallback(void *refCon, io_iterator_t iterator) {
    io_service_t device;
    while ((device = IOIteratorNext(iterator))) {
        // 读取设备产品名判断是否为iPhone/iPad
        CFStringRef productNameRef = IORegistryEntryCreateCFProperty(device, CFSTR(kUSBProductString), kCFAllocatorDefault, 0);
        if (productNameRef) {
            NSString *productName = (__bridge_transfer NSString *)productNameRef;
            if ([productName containsString:@"iPhone"] || [productName containsString:@"iPad"]) {
                // 切换到主线程更新UI
                dispatch_async(dispatch_get_main_queue(), ^{
                    // 这里调用你自己的NSView提示展示逻辑
                    NSLog(@"设备接入: %@", productName);
                });
            }
        }
        IOObjectRelease(device);
    }
}

// 设备断开回调
void DeviceRemovedCallback(void *refCon, io_iterator_t iterator) {
    io_service_t device;
    while ((device = IOIteratorNext(iterator))) {
        CFStringRef productNameRef = IORegistryEntryCreateCFProperty(device, CFSTR(kUSBProductString), kCFAllocatorDefault, 0);
        if (productNameRef) {
            NSString *productName = (__bridge_transfer NSString *)productNameRef;
            if ([productName containsString:@"iPhone"] || [productName containsString:@"iPad"]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    // 这里调用你自己的NSView提示移除逻辑
                    NSLog(@"设备断开: %@", productName);
                });
            }
        }
        IOObjectRelease(device);
    }
}

实现资源释放方法,避免内存泄漏:

- (void)stopMonitoringIOSDevices {
    if (gAddedIter) {
        IOObjectRelease(gAddedIter);
        gAddedIter = 0;
    }
    if (gRemovedIter) {
        IOObjectRelease(gRemovedIter);
        gRemovedIter = 0;
    }
    if (gNotifyPort) {
        IONotificationPortDestroy(gNotifyPort);
        gNotifyPort = NULL;
    }
}

注意事项

  • 所有UI更新操作必须切换到主线程执行,否则会出现界面异常或崩溃
  • 如果需要更精准的过滤,避免把其他Apple USB外设(比如妙控键盘、鼠标)纳入检测,可以在回调中额外匹配设备Product ID,接入对应设备打印PID后自行添加过滤规则即可
  • 若应用使用沙盒机制,必须开启USB访问权限,否则无法获取USB设备信息

内容的提问来源于stack exchange,提问作者Edward Chou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:27:05