NSURLSession下载远程图片遭遇NSPOSIXErrorDomain Code=28设备空间不足错误的疑难问题咨询
我之前在处理iOS图片下载逻辑时,确实碰到过一模一样的迷惑情况!明明用户设备磁盘空间充足,事后测试也完全正常,但就是有极少数用户会触发这个“磁盘空间不足”的错误,而且重新加载就恢复正常。结合当时的排查经验,给你几个可能的方向:
1. NSURLSession默认缓存的瞬时配额耗尽
NSURLSession依赖的URLCache默认会给磁盘缓存设置一个固定配额(默认大概几十MB),如果短时间内有大量图片下载请求,可能会把这个缓存配额临时占满——哪怕设备总磁盘空间还剩很多。这种情况下系统就会抛出“空间不足”的错误,但重新加载时,缓存可能已经被自动清理了一部分,所以就能正常下载了。
可以试试自定义URLCache,给它设置更大的磁盘容量:
let cacheSizeMemory = 50 * 1024 * 1024 // 50MB内存缓存 let cacheSizeDisk = 200 * 1024 * 1024 // 200MB磁盘缓存 let urlCache = URLCache(memoryCapacity: cacheSizeMemory, diskCapacity: cacheSizeDisk, diskPath: "CustomImageCache") URLCache.shared = urlCache
2. 系统临时目录的瞬时空间不足
NSURLSession下载时默认会把临时文件写到系统的临时目录(NSTemporaryDirectory()),这个目录会被系统定期清理,但如果刚好在下载的瞬间,这个目录被其他进程的临时文件占满了(比如系统同步、其他应用突发下载),就会触发错误。而你之后测试文件创建时,系统可能已经自动清理了临时目录,所以看不到异常。
建议把下载的临时路径改到应用自己的缓存目录里,比如:
let cacheDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first! let tempDownloadPath = cacheDir.appendingPathComponent("TempImageDownloads") // 确保目录存在 try? FileManager.default.createDirectory(at: tempDownloadPath, withIntermediateDirectories: true) // 配置NSURLSession时指定临时目录 let configuration = URLSessionConfiguration.default configuration.temporaryDirectory = tempDownloadPath let session = URLSession(configuration: configuration)
3. 文件系统inode耗尽(小众但可能)
有时候磁盘空间看似充足,但文件系统的inode(用来记录文件元数据的节点)被耗尽了,也会抛出“No space left on device”的错误。这种情况在iOS上比较少见,但如果用户设备上有大量小文件(比如缓存的小图片、细碎日志),就有可能发生。
你可以在错误发生时,通过statfs函数获取文件系统的inode使用情况,排查是否是这个问题:
#include <sys/statfs.h> - (void)checkInodeUsage { struct statfs statInfo; NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; if (statfs([cachePath UTF8String], &statInfo) == 0) { unsigned long long freeInodes = statInfo.f_ffree; unsigned long long totalInodes = statInfo.f_files; NSLog(@"Free inodes: %llu, Total inodes: %llu", freeInodes, totalInodes); } }
4. NSURLSession任务的瞬时冲突
虽然你用的是单个NSURLSession,但如果同时发起了多个下载任务,可能会出现临时文件写入的竞争,导致系统误判磁盘空间不足。这种情况下,限制并发任务数,或者在下载失败后先清理当前session的临时文件再重试,可能会缓解问题。
另外,建议在错误回调里收集更多上下文信息:比如错误发生时设备的总磁盘空间、缓存目录可用空间、临时目录可用空间,这些数据能帮你更快定位问题。
内容的提问来源于stack exchange,提问作者qing

