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

如何通过IP/MAC地址获取网络中苹果设备的Model Identifier?

问题解答

一、通用获取苹果设备Model Identifier的方法

苹果设备确实会通过_device-info._tcp这个Bonjour服务发布Model Identifier(如Macmini9,1),该服务在Ventura系统下完全可用——Finder就是依赖它获取设备专属图标和信息的。你之前的代码未收到TXT消息,主要是因为硬编码服务名称的方式不可靠,正确的做法是先通过NetServiceBrowser动态发现局域网内的_device-info._tcp服务,再解析对应服务的TXT记录。

修正后的代码示例

import Foundation

class AppleDeviceInfoScanner: NSObject, NetServiceBrowserDelegate, NetServiceDelegate {
    private let browser = NetServiceBrowser()
    
    func startScanning() {
        browser.delegate = self
        // 搜索本地局域网内的_device-info._tcp服务
        browser.searchForServices(ofType: "_device-info._tcp", inDomain: "local.")
    }
    
    // NetServiceBrowserDelegate:发现可用服务
    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
        service.delegate = self
        // 主动解析服务的地址和TXT记录,超时时间设为5秒
        service.resolve(withTimeout: 5.0)
    }
    
    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
        // 处理设备离线逻辑(可选)
    }
    
    // NetServiceDelegate:解析成功,提取Model Identifier
    func netServiceDidResolveAddress(_ service: NetService) {
        guard let txtData = service.txtRecordData(),
              let txtDict = NetService.dictionary(fromTXTRecord: txtData) else {
            return
        }
        
        // Model Identifier存储在"model"键对应的TXT数据中
        if let modelData = txtDict["model"], let modelId = String(data: modelData, encoding: .utf8) {
            print("设备名称:\(service.name) | Model Identifier:\(modelId)")
        }
        
        // 额外可提取的信息:设备类型ID(deviceid)、系统版本(osvers)等
        if let osVersionData = txtDict["osvers"], let osVersion = String(data: osVersionData, encoding: .utf8) {
            print("系统版本:\(osVersion)")
        }
    }
    
    func netService(_ service: NetService, didNotResolve errorDict: [String : NSNumber]) {
        print("解析服务失败:\(service.name),错误信息:\(errorDict)")
    }
}

// 使用方式
let scanner = AppleDeviceInfoScanner()
scanner.startScanning()

关键注意事项

  • 权限配置:Ventura对局域网访问权限要求严格,必须在Info.plist中添加以下配置:
    • 添加NSBonjourServices数组,包含字符串_device-info._tcp
    • 添加NSLocalNetworkUsageDescription字符串,说明局域网访问的用途(比如"用于发现局域网内的苹果设备信息")
  • 兼容性:大部分现代苹果设备(2013年后的Mac、iOS 10+的移动设备、Apple TV 4+)都会发布_device-info._tcp服务,旧款设备可能不支持。

二、获取网络设备厂商名称的方法

厂商名称可通过MAC地址的**OUI(组织唯一标识符)**查询——MAC地址的前3字节是厂商的唯一标识。可以直接解析macOS系统内置的OUI数据库,无需依赖外部接口。

实现代码示例

func getDeviceVendor(from macAddress: String) -> String? {
    // macOS系统内置的OUI数据库路径
    let ouiFileURL = URL(fileURLWithPath: "/usr/share/misc/oui.txt")
    guard let ouiContent = try? String(contentsOf: ouiFileURL) else {
        return nil
    }
    
    // 格式化MAC地址:去掉分隔符,提取前6位并转为大写
    let cleanMacPrefix = macAddress.replacingOccurrences(of: ":", with: "")
                                   .replacingOccurrences(of: "-", with: "")
                                   .prefix(6)
                                   .uppercased()
    
    // 遍历OUI内容匹配厂商
    for line in ouiContent.components(separatedBy: .newlines) {
        if line.contains(cleanMacPrefix) {
            let lineParts = line.components(separatedBy: .whitespaces).filter { !$0.isEmpty }
            if lineParts.count >= 3 {
                return lineParts[2...].joined(separator: " ")
            }
        }
    }
    return nil
}

// 使用示例
if let vendor = getDeviceVendor(from: "00:1A:2B:3C:4D:5E") {
    print("设备厂商:\(vendor)")
}

补充说明

部分设备的Bonjour TXT记录中会包含vendor字段,可以优先尝试读取该字段,但OUI解析的方式兼容性更强,适用于所有网络设备。

三、关于_device-info._tcp在Ventura的可用性确认

该服务在Ventura下完全正常工作,你的代码未收到TXT消息的核心原因:

  1. 服务名称不匹配:硬编码的设备名称(如Mac-Mini.local.)可能与设备实际发布的Bonjour名称不符(比如设备名称包含空格、特殊字符),必须通过NetServiceBrowser动态发现服务
  2. 未主动解析:直接调用startMonitoring()不会触发服务解析,需要调用resolve(withTimeout:)主动获取服务的地址和TXT数据
  3. 权限缺失:未在Info.plist中配置局域网访问权限,被系统拦截了服务请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:22:57