![](/img/trans.png)
[英]How to resolve memory cycle in Swift 4 URLSession.downloadTask?
[英]Swift: How to catch disk full error on background URLSession.downloadTask?
我正在努力理解我認為會很容易的事情。
我有一個URLSession.downloadTask。 我已將下載對象設置為URLSession委托,並且以下委托方法確實會接收調用,因此我知道我的委托設置正確。
func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?)
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
我無法捕獲的情況是downloadTask填滿了iPad上的磁盤空間。 這些委托方法均未調用。
我應該如何捕捉此錯誤?
這是我的下載對象:
import Foundation
import Zip
import SwiftyUserDefaults
extension DownloadArchiveTask: URLSessionDownloadDelegate {
// Updates progress info
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
didWriteData bytesWritten: Int64, totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64) {
let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
self.delegate?.updateProgress(param: progress)
}
// Stores downloaded file
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("DownloadArchiveTask: In didFinishDownloadingTo")
}
}
extension DownloadArchiveTask: URLSessionTaskDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
print("DownloadArchiveTask: In didCompleteWithError")
if error != nil {
print("DownloadArchiveTask: has error")
self.delegate?.hasDiskSpaceIssue()
}
}
}
extension DownloadArchiveTask: URLSessionDelegate {
// Background task handling
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
print("DownloadArchiveTask: In handler for downloading archive")
DispatchQueue.main.async {
let sessionIdentifier = session.configuration.identifier
if let sessionId = sessionIdentifier, let app = UIApplication.shared.delegate as? AppDelegate, let handler = app.completionHandlers.removeValue(forKey: sessionId) {
handler()
}
}
}
func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
print("DownloadArchiveTask: didBecomeInvalidWithError")
if error != nil {
print("DownloadArchiveTask: has error")
self.delegate?.hasDiskSpaceIssue()
}
}
}
class DownloadArchiveTask: NSObject {
var delegate: UIProgressDelegate?
var archiveUrl:String = "http://someurl.com/archive.zip"
var task: URLSessionDownloadTask?
static var shared = DownloadArchiveTask()
// Create downloadsSession here, to set self as delegate
lazy var session: URLSession = {
let configuration = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background_archive")
return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}()
func initialDownload() {
// Create URL to the source file you want to download
let fileURL = URL(string: archiveUrl)
let request = URLRequest(url:fileURL!)
self.task = self.session.downloadTask(with: request)
task?.resume()
}
}
有人做過嗎? 我不敢相信這會很難-我必須以錯誤的方式解決問題...
不久前,我不得不為公司解決這個問題。 現在我的解決方案是在Objective C中進行的,因此您必須將其轉換為Swift,這並不難。 我創建了一個方法,該方法將可用存儲空間留在設備上,然后根據我們正在下載的文件的大小檢查該方法。 我的解決方案假定您知道下載文件的大小,在這種情況下,可以在didWriteData
方法中使用totalBytesExpectedToWrite
參數。
這是我所做的:
+ (unsigned long long)availableStorage
{
unsigned long long totalFreeSpace = 0;
NSError* error = nil;
NSArray* paths = NSSearchPathForDirectoriesInDomain(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary* dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error:&error];
if (dictionary)
{
NSNumber* freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
}
return totalFreeSpace;
}
由於這些iTunes,設備上的設置應用程序和此號碼永遠不匹配,因此請確保為這些號碼留些錯誤的空間。 我們在這里得到的數字是三個中的最小數字,以MB為單位。 希望對您有所幫助,如果您需要幫助將其轉換為Swift,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.