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

iOS设备Alamofire网络请求出现NSPOSIXErrorDomain Code=28错误的原因分析及预防方案咨询

Understanding and Fixing POSIX Error Code 28 ("No space left on device") in Alamofire/iOS

Great question—this error is tricky because it’s not actually tied to your device’s total available disk or memory. Let’s break down what’s causing it and how to fix it.

Why Does Error Code 28 Happen (Even With Free Space)?

POSIX error code 28 maps to ENOSPC, which translates to "no space left on device"—but in iOS, this can trigger from sandboxed storage limits or resource exhaustion that has nothing to do with your device’s overall free space. Here are the most likely culprits for your scenario:

  • App-Specific Cache/Temporary Directory Quota
    iOS enforces per-app storage quotas for cache and temporary directories, even if the device has plenty of free space. If Alamofire’s default URLSession cache or your app’s own temporary files fill up this quota, you’ll hit this error. This is especially common with frequent requests (like your 5-second location check) that generate cached data over time.

  • File Descriptor Exhaustion
    Every network request (via Alamofire’s DataTask) uses a file descriptor. If your app spawns too many concurrent requests, or fails to properly clean up finished/canceled tasks, you can hit the iOS per-app file descriptor limit. This is easy to miss because it doesn’t show up in standard disk/memory stats.

  • iOS 14+ Sandbox Storage Changes
    iOS 14 tightened sandbox storage rules, including how apps use cache directories. If your cached files aren’t marked as eligible for system cleanup (e.g., missing the NSURLIsExcludedFromBackupKey attribute), the system may restrict your app’s cache usage even if space is available.

  • Misconfigured Alamofire/URLSession Cache
    If you haven’t customized Alamofire’s cache settings, the default URLSession cache might be set to an overly large size, or it might not prune old entries automatically. Over time, this can eat into your app’s storage quota.

How to Prevent This Error

Here are actionable steps to fix and avoid the issue:

1. Limit Concurrent Requests and Clean Up Tasks

Since your app sends a request every 5 seconds (when the user moves), make sure you’re not spawning more requests than necessary:

  • Set a maximum concurrent request limit in your Alamofire Session:
    let sessionConfiguration = URLSessionConfiguration.default
    let session = Session(
        configuration: sessionConfiguration,
        maximumConcurrentRequests: 2 // Adjust based on your app's needs
    )
    
  • Always cancel unused requests (e.g., when a view controller is dismissed or the user stops moving):
    // Store a reference to your pending request
    var pendingLocationRequest: DataRequest?
    
    // Cancel when no longer needed
    pendingLocationRequest?.cancel()
    

2. Customize and Prune Alamofire’s Cache

Tweak the URLSession cache to stay within your app’s quota:

  • Set explicit memory and disk cache limits when initializing your Alamofire Session:
    let cache = URLCache(
        memoryCapacity: 10 * 1024 * 1024, // 10MB in-memory cache
        diskCapacity: 50 * 1024 * 1024,   // 50MB disk cache
        diskPath: nil
    )
    let sessionConfiguration = URLSessionConfiguration.default
    sessionConfiguration.urlCache = cache
    let session = Session(configuration: sessionConfiguration)
    
  • Periodically clear old cache entries to free up space:
    // Clear all cached responses
    URLCache.shared.removeAllCachedResponses()
    
    // Or clear cache for specific request URLs
    URLCache.shared.removeCachedResponse(for: URLRequest(url: yourLocationAPIURL))
    

3. Monitor and Clean Up Temporary/Cache Directories

Keep tabs on your app’s storage usage and clean up when needed:

  • Use this helper function to calculate the size of your cache directory:
    func calculateDirectorySize(at url: URL) -> UInt64 {
        guard let enumerator = FileManager.default.enumerator(
            at: url,
            includingPropertiesForKeys: [.fileSizeKey],
            options: .skipsHiddenFiles
        ) else { return 0 }
    
        var totalSize: UInt64 = 0
        for case let fileURL as URL in enumerator {
            do {
                let attributes = try fileURL.resourceValues(forKeys: [.fileSizeKey])
                if let size = attributes.fileSize {
                    totalSize += UInt64(size)
                }
            } catch {
                continue
            }
        }
        return totalSize
    }
    
  • When the cache size exceeds a threshold (e.g., 40MB), delete old files or clear the entire cache.

4. Mark Cache Files as Eligible for System Cleanup

Ensure your app’s cache files are marked so iOS can automatically clean them when low on space:

func markFileAsCleanable(at url: URL) {
    do {
        try url.setResourceValue(true, forKey: .isExcludedFromBackupKey)
    } catch {
        print("Failed to mark file as cleanable: \(error)")
    }
}

Apply this to any cached files your app generates (not just Alamofire’s default cache).

5. Update Alamofire to the Latest Version

Older versions of Alamofire had occasional resource leaks with URLSession tasks. Updating to the latest stable release can fix hidden issues that lead to file descriptor or storage exhaustion.

内容的提问来源于stack exchange,提问作者J. van 't Veld

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:22:51