Swift: Как отловить ошибку переполнения диска на фоне URLSession.downloadTask? - PullRequest
1 голос
/ 22 марта 2019

Я изо всех сил пытаюсь понять, что я думал, будет легко.

У меня есть 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()

    }
}

Кто-нибудь делал это раньше? Я не могу поверить, что это так сложно - я, должно быть, неправильно подхожу к проблеме ...

1 Ответ

0 голосов
/ 22 марта 2019

Я должен был решить эту проблему для своей компании не так давно.Теперь мое решение в Objective C, поэтому вам придется преобразовать его в Swift, что не должно быть так сложно.Я создал метод, который получил доступное место на устройстве, а затем проверил его по размеру загружаемого файла.Мое решение предполагает, что вы знаете размер загружаемого файла, в вашем случае вы можете использовать параметр totalBytesExpectedToWrite в методе didWriteData.

Вот что я сделал:

+ (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, приложение настроек на устройстве и этот номер никогда не совпадают.Число, которое мы здесь получаем, является наименьшим из трех и указывается в МБ.Я надеюсь, что это поможет, и дайте мне знать, если вам нужна помощь в преобразовании его в Swift.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...