如何快速获取应用程序的总占用大小?
你遇到的url.resourceValues(forKeys:)返回异常大小的核心原因是用错了资源键:普通的fileSizeKey仅会返回文件/目录本身的元数据占用大小,目录本身的元数据通常只有几十字节,所以会出现0、96字节这类结果,不会自动递归计算目录下所有内容的总大小。
而第三方文件管理器可以瞬间拿到应用大小,核心是用了以下两种无需自行遍历目录的方案:
方案1:读取Spotlight索引元数据(效率最高)
macOS的Spotlight服务会在后台自动索引所有磁盘文件的元数据,包括目录总大小,直接读取已经索引好的结果即可毫秒级返回大小,和Finder显示的数值完全一致。
需要导入CoreServices框架,示例代码如下:
import CoreServices /// 获取指定路径的逻辑总大小(对应Finder显示的「大小」) func getBundleSize(path: String) -> Int64? { guard let mdItem = MDItemCreate(nil, path as CFString), let sizeValue = MDItemCopyAttribute(mdItem, kMDItemLogicalSize) as? Int64 else { return nil } return sizeValue }
如果需要获取实际磁盘占用大小,把kMDItemLogicalSize换成kMDItemPhysicalSize即可。
注意:该方案仅对已加入Spotlight索引的路径生效,如果是未开索引的外置磁盘、系统保护目录,可以用第二种方案。
方案2:使用系统自带的目录大小计算API
苹果官方提供了专门的目录总大小查询键,无需自行实现递归遍历,底层是系统内核级实现,比自行遍历的效率高3~10倍:
func getDirectoryTotalSize(url: URL) throws -> Int64? { let keys: Set<URLResourceKey> = [.isDirectoryKey, .totalFileSizeKey, .totalFileAllocatedSizeKey] let values = try url.resourceValues(forKeys: keys) // 非目录直接返回单文件大小 guard values.isDirectory == true else { return values.fileSize.map(Int64.init) } // 返回目录逻辑总大小,需物理占用大小可换用totalFileAllocatedSize return values.totalFileSize.map(Int64.init) }
这里的totalFileSizeKey会自动递归计算目录下所有子文件、子目录的大小总和,自动处理符号链接、嵌套Bundle等特殊结构,结果和Finder一致。
内容的提问来源于stack exchange,提问作者Const
相关产品推荐
相关产品推荐

