开启shouldCompactOnLaunch后Realm初始化报空间不足但实际容量足够
异常说明
你遇到的是Realm初始化阶段的磁盘空间不足报错:
failed: No space left on device" UserInfo={NSLocalizedDescription=write() failed: No space left on device, Error Code=1})
核心问题原因
1. 可用空间统计逻辑不准确
你当前使用的两类获取可用空间的API都存在统计值偏低的问题:
volumeAvailableCapacityKey仅统计了非可 purgeable 类型的可用空间,iOS系统中可被自动清理的缓存、临时文件等空间不会被计入该值,但这些空间在写入重要数据时是可以被系统释放使用的- 兜底用的
systemFreeSize是已过时的文件系统属性API,同样不会计入可清理空间,统计值和实际可用空间偏差可达数GB
如果需要获取真实的可用写入空间,应该使用volumeAvailableCapacityForImportantUsageKey这个API。
2. 压缩所需空间计算阈值偏低
Realm开启shouldCompactOnLaunch后的压缩逻辑,需要先创建完整的新数据库文件再替换旧文件,整个过程需要的冗余空间至少为当前Realm文件总大小的2倍,你当前仅判断可用空间大于文件大小就执行压缩,阈值设置过低,很容易触发空间不足。
此外你统计的文件大小仅为逻辑大小,没有计入Realm内部碎片化的空闲页占用,实际需要的冗余空间会比你计算的更高。
3. 并发写入挤占空间
如果在Realm初始化压缩的同时,应用有其他线程在执行磁盘写入操作(比如日志写入、资源缓存等),会在压缩过程中消耗可用空间,导致哪怕启动前统计的空间足够,压缩过程中仍然出现空间不足报错。
修复方案
- 替换可用空间统计逻辑,改用
volumeAvailableCapacityForImportantUsageKey获取真实可用容量 - 调整压缩触发的判断逻辑,只有当可用空间大于等于当前Realm文件大小的2倍时,才允许执行启动压缩
- 给
shouldCompactOnLaunch增加降级逻辑,当可用空间不足时自动跳过压缩,优先保证数据库正常启动,后续应用空闲且空间充足时再手动触发压缩 - 启动初始化Realm的阶段,暂时暂停其他非必要的磁盘写入任务,避免空间被挤占
内容的提问来源于stack exchange,提问作者blyabtroi
相关产品推荐
相关产品推荐

