问题
I'm having issues with handling "out of space" / "full disk" errors on ios with NSURLSessionDownloadTask
If the disk is full due to downloads done in the app I get a call to
URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?)
with the error having domain NSPOSIXErrorDomain and error code ENOSPC
But this only happens once for a task, not for all running
Ex: If I have 3 tasks running at the time, I only get this for one of them and the other 2 remain in the state Running They don't receive any bytes, but they don't fail either. Moreovever, calling cancel on any of those tasks changes their state from Running to Cancelling and they remain like this indefinitely.
My solution was, when I receive this error the first time, to call invalidateAndCancel for the session and handle failure for all running tasks. This seems to work when the "full disk" is caused by the downloads made by the app. But if "full disk" error is caused by external downloads (Ex: iTunes file sharing, downloading Podcasts, other apps downloading) I receive no error in the app All my download tasks remain in Running, or Cancelling (if I try to cancel them) They don't download anything, they don't fail with any of the callbacks for NSURLSessionDelegate or NSURLSessionDownloadDelegate
Before starting a download, I check the available space available on device I also take into consideration the currently Running tasks But I have no control over other downloads on the device that might end up triggering the "full disk" warning
How can I handle these cases? Are the download tasks expected to remain in Running state though they are not downloading anymore? Shouldn't I get a didCompleteWithError call with (NSPOSIXErrorDomain, ENOSPC) for each task, or for the session at least? Or at least shouldn't I be able to successfully cancel them? and get a didCompleteWithError call anyway?
Is there a delegate call I'm missing, one that would let me know it's time to close all running tasks?
I'm using a shared background session for more background download tasks
The download tasks are created with NSURLSession's: func downloadTaskWithRequest(_ request: NSURLRequest) -> NSURLSessionDownloadTask
The sesion configuration is created using NSURLSessionConfiguration's: class func backgroundSessionConfigurationWithIdentifier(_ identifier: String) -> NSURLSessionConfiguration
The seesion is created using, NSURLSession's init(configuration configuration: NSURLSessionConfiguration, delegate delegate: NSURLSessionDelegate?, delegateQueue queue: NSOperationQueue?)
I'm using a NSOperationQueue with a maxConcurrentOperationCount of 3 I have implemented my NSURLSessionDelegate and NSURLSessionDownloadDelegate
Tasks seem to run fine in foreground and background.
Thanks
Ps: using Xocde7, ios9 sdk, tested on an ios9 device
回答1:
I had also asked Apple about this issue and the answer came back:
Seems like, because the background session uses the disk to persist its state, behaviour when the disk is full is not exactly reliable to return the ENOSPC
And the handling of full disk case is the developer's responsibility for now by:
checking for disk space before you start a download
monitor disk space when your app is downloading — If your app is in the foreground, or your app gets resumed (or relaunched) in the background, actively monitor the disk space available. If it’s below some threshold, suspend your downloads (by calling -cancelByProducingResumeData:, so you can resume them later on).
For a detailed answer check: https://forums.developer.apple.com/thread/43263
来源:https://stackoverflow.com/questions/36133758/nsurlsessiondownloadtask-issues-with-storage-almost-full-disk-warnings