MacOS下如何用Swift正确获取U盘的总、可用、已用存储空间?
问题根源定位
你当前代码返回系统盘空间的原因非常明确:
- 原路径拼接逻辑强行假设应用一定放在U盘根目录下,完全没有做实际路径校验。如果应用是在系统盘上运行、或是被放在U盘的多级子目录中,拼出来的路径根本不是U盘的挂载根目录,查询范围落在系统盘路径里,自然会返回系统盘的容量值。
- 旧版macOS存在兼容特性:只要查询容量的路径不是卷的挂载根节点,系统就会默认返回上层内置盘的容量信息,不会自动识别路径实际所属的外接卷。
修正后的完整实现
1. 精准定位U盘挂载根路径
放弃手动拼接固定层级的写法,从应用的Bundle路径开始逐层向上回溯,直到匹配到/Volumes下的一级子目录(即外接卷的实际挂载点),该逻辑不受应用在U盘内的存放深度影响,可靠性最高。
static func getUSBRootURL() -> URL? { let bundleURL = Bundle.main.bundleURL var currentURL = bundleURL let volumesRootURL = URL(fileURLWithPath: "/Volumes") // 逐层向上遍历路径 while currentURL.path != "/" { // 判断当前路径的上一级是否为/Volumes目录,是则当前路径就是外接卷根目录 if currentURL.deletingLastPathComponent() == volumesRootURL { return currentURL } currentURL.deleteLastPathComponent() } return nil }
2. 获取卷的完整空间信息
在拿到准确的卷根路径后,通过系统API批量查询总容量、可用容量,再计算得到已用容量,查询结果会和Finder显示的数值基本一致。
func getUSBSpaceInfo() -> (total: Int64, available: Int64, used: Int64)? { guard let rootURL = getUSBRootURL() else { return nil } if #available(macOS 10.13, *) { // 定义需要查询的容量相关资源键 let resourceKeys: Set<URLResourceKey> = [ .volumeTotalCapacityKey, .volumeAvailableCapacityForImportantUsageKey ] guard let values = try? rootURL.resourceValues(forKeys: resourceKeys), let totalCap = values.volumeTotalCapacity, let availableCap = values.volumeAvailableCapacityForImportantUsage else { return nil } let usedCap = totalCap - availableCap return (Int64(totalCap), Int64(availableCap), Int64(usedCap)) } else { // 适配低版本macOS的 fallback 逻辑 guard let fsAttrs = try? FileManager.default.attributesOfFileSystem(forPath: rootURL.path), let total = fsAttrs[FileAttributeKey.systemSize] as? NSNumber, let free = fsAttrs[FileAttributeKey.systemFreeSize] as? NSNumber else { return nil } let used = total.int64Value - free.int64Value return (total.int64Value, free.int64Value, used) } }
常见踩坑说明
- 不要手动写死路径层级拼接:外接卷的路径深度可能随应用存放位置变化出现偏移,逐层回溯到/Volumes下的子目录是唯一不会出错的定位方式。
- 不要在非挂载根路径上查询容量:即使路径确实属于U盘目录,只要查询时传入的不是
/Volumes/卷名这个层级的路径,部分系统版本就会错误返回系统盘的容量信息。 - 对于exFAT、FAT32格式的U盘,API返回的总容量和Finder显示的数值会有轻微差异,这是文件系统保留块、元数据占用导致的,属于正常现象。
内容的提问来源于stack exchange,提问作者Monty
相关产品推荐
相关产品推荐

