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

如何利用.volumeAvailableCapacityForImportantUsageKey报告的可用空间?

iOS 如何利用 volumeAvailableCapacityForImportantUsageKey 返回的额外可用空间

可以通过多种方式查询iOS设备的可用空间,其中volumeAvailableCapacityForImportantUsageKey会返回更高的容量值——这是因为系统允许在存储重要内容时,自动清理临时/非重要文件来腾出空间。但实际测试时,一旦写入量达到常规可用容量(比如volumeAvailableCapacityKey、NSFileManager或boost::filesystem::space.available返回的值),应用就会崩溃,报错:[general] Encountered write failure 28 No space left on device。

测试用的写入代码如下:

func writeFile(size: Measurement<UnitInformationStorage>) {
    deleteFile()
    
    let filename = getDocumentsDirectory().appendingPathComponent("output.txt")

    var megabyteOfData: [UInt8] = []
    for i in 0..<1024*1024 {
        megabyteOfData.append(UInt8(i % 0xff))
    }
    
    let data = Data(bytes: &megabyteOfData, count: megabyteOfData.count * MemoryLayout<UInt8>.stride)

    do {
        let chunks = Int(size.converted(to: UnitInformationStorage.megabytes).value)
        
        try data.write(to: filename, options: .atomicWrite)
        
        let fileHandle = try FileHandle(forWritingTo: filename)
        for i in 2...chunks {
            print("Writing \(i) chunk...")
            fileHandle.write(data)
        }
        try fileHandle.close()
    }
    catch {
        print(error)
    }
}

问题核心

iOS不会在你写入文件时自动触发临时文件清理,你需要主动清理自身临时文件,并在遇到空间不足时给系统时间回收可释放空间,才能利用volumeAvailableCapacityForImportantUsageKey对应的额外容量。

解决方案

1. 提前获取并校验重要可用空间

在写入前,先确认要写入的文件大小不超过volumeAvailableCapacityForImportantUsageKey返回的值,避免无效操作:

func getImportantAvailableSpace() -> Measurement<UnitInformationStorage>? {
    let documentsDir = getDocumentsDirectory()
    do {
        let resourceValues = try documentsDir.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
        if let capacity = resourceValues.volumeAvailableCapacityForImportantUsageKey {
            return Measurement(value: Double(capacity), unit: UnitInformationStorage.bytes)
        }
    } catch {
        print("获取重要可用空间失败: \(error)")
    }
    return nil
}

// 调用示例
if let availableSpace = getImportantAvailableSpace(), size <= availableSpace {
    writeFile(size: size)
} else {
    print("重要可用空间不足")
}

2. 主动清理自身临时文件

在写入大文件前,先清理应用自身的临时文件和缓存,腾出基础空间的同时,触发系统的空间回收机制:

func cleanupLocalTempFiles() throws {
    // 清理临时目录文件
    let tempDir = FileManager.default.temporaryDirectory
    for file in try FileManager.default.contentsOfDirectory(at: tempDir, includingPropertiesForKeys: nil) {
        try FileManager.default.removeItem(at: file)
    }
    
    // 清理缓存目录中可删除的文件
    let cachesDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
    for file in try FileManager.default.contentsOfDirectory(at: cachesDir, includingPropertiesForKeys: nil) {
        try FileManager.default.trashItem(at: file, resultingItemURL: nil)
    }
}

3. 写入时增加错误重试逻辑

当遇到空间不足错误时,不要直接崩溃,等待系统完成临时文件清理后重试:

func writeFile(size: Measurement<UnitInformationStorage>) {
    deleteFile()
    
    let filename = getDocumentsDirectory().appendingPathComponent("output.txt")

    var megabyteOfData: [UInt8] = []
    for i in 0..<1024*1024 {
        megabyteOfData.append(UInt8(i % 0xff))
    }
    
    let data = Data(bytes: &megabyteOfData, count: megabyteOfData.count * MemoryLayout<UInt8>.stride)

    do {
        // 先清理本地临时文件
        try cleanupLocalTempFiles()
        
        let chunks = Int(size.converted(to: UnitInformationStorage.megabytes).value)
        
        try data.write(to: filename, options: .atomicWrite)
        
        let fileHandle = try FileHandle(forWritingTo: filename)
        for i in 2...chunks {
            print("Writing \(i) chunk...")
            do {
                fileHandle.write(data)
            } catch let error as NSError where error.code == 28 {
                // 遇到空间不足,等待系统清理后重试
                Thread.sleep(forTimeInterval: 1.5)
                fileHandle.write(data)
            }
        }
        try fileHandle.close()
    } catch {
        print(error)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 14:02:58