将CoreSessionDownloadTask存储在Core Data中

时间:2017-06-02 10:35:31

标签: ios swift core-data nsurlsessiondownloadtask urlsessiontask

当app处于关闭状态或我的下载状态发生变化时,例如从等待状态到下载状态或已完成状态,我想在核心数据中保存URLSessionDownloadTask

我的自定义类的所有其他属性都存储得很完美,但应用程序在存储下载任务时会崩溃。

崩溃的原因是

  

[__ NSCFLocalDownloadTask encodeWithCoder:]:无法识别的选择器发送到实例0x7ff189f181c0    - [NSKeyedArchiver dealloc]:警告:NSKeyedArchiver在没有调用-finishEncoding的情况下解除分配。    因未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:' - [__ NSCFLocalDownloadTask encodeWithCoder:]:无法识别的选择器发送到实例0x7ff189f181c0'

这是我的班级

class VideoDownloadModel : NSManagedObject {

    @NSManaged var videoID : NSNumber?
    @NSManaged var vid : Video?
    @NSManaged var downloadTask : URLSessionDownloadTask?
    @NSManaged var downloadStatus : String?
}

像这样存储

    let request = NSFetchRequest<NSFetchRequestResult>(entityName: (COREDATA_ENTITY_Description?.name)!)
    request.returnsObjectsAsFaults = false
    request.predicate = NSPredicate(format: "videoID == %@", videoModel.videoID!)

        do {
            let result = try COREDATA_CONTEXT.fetch(request)
            print(result)
            var vidArr = result as! [VideoDownloadModel]

            if vidArr.count != 0 {
                vidArr[0] = videoModel

                COREDATA_MANAGER.saveContext()
            }

        } catch {
            let fetchError = error as NSError
            print(fetchError)
        }

URLSessionDownlaodTasknil时,它可以正常工作,但是当任何下载开始时,它会在保存时崩溃。

scenerio:

  • 我使用所有属性初始化了我的自定义类对象,但将task设置为nil。

  • 我将该对象存储在它保存完好的核心数据中。

  • 我初始化该对象的任务,下载工作完美。

  • 然后我更新核心数据中的对象,同时更新应用程序崩溃,因为URLSssionTask不是从NSCoding继承的。所以它没有编码和解码方法。

我想要一些解决方案来解决这个问题

任何帮助将不胜感激。感谢。

2 个答案:

答案 0 :(得分:1)

您无法将URLSessionDownloadTask保存在核心数据中,因为 - 如您所述 - 它不符合NSCoding。在许多情况下,答案是编写自己的代码以转换为/ Data,但在这种情况下不起作用。 URLSessionDownloadTask只能由URLSession创建,因此您无法序列化和反序列化任务对象。

这并不重要,因为保存和恢复它们没有意义。 URLSessionDownloadTask表示应用程序运行时正在进行的操作。如果您的应用已关闭,则该活动结束。在应用关闭并重新启动后恢复URLSessionDownloadTask没有意义,因为它没有活动来表示。基本上,即使您可以存储任务对象并将其恢复,恢复后也无济于事。没有理由打扰。

如果您希望恢复不完整的下载,则必须从头开始。创建您的URLSession,然后使用它来创建新的URLSessionDownloadTask。如果您对获取有关后台下载的信息感兴趣,可以将会话对象与getTasksWithCompletionHandler(_:)一起使用,以确定它们是否已完成。

答案 1 :(得分:0)

保存URLSessionDownloadTask没有意义。实际上,您希望在暂停时保存从downloadTask.cancel(byProducingResumeData: )获取的数据。

一旦您需要恢复下载,请使用downloadTaskWithResumeData(:)并继续创建包含已保存数据的新下载任务。

当应用终止时 - 不包括用户强行终止应用的情况。

关于URLSession的Apple文档清楚地解释了当应用程序终止时该怎么做 来自文档 - 在iOS和OS X中,当用户重新启动您的应用时,您的应用应立即创建后台配置对象,其标识与您上次运行应用时具有未完成任务的任何会话相同,然后创建每个配置对象的会话。这些新会话同样会自动与正在进行的后台活动重新关联。

当用户强行终止应用时

在这种情况下,将触发URLSession委托urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?),其中userInfo对象中的error dict将具有与密钥NSURLSessionDownloadTaskResumeData对应的恢复数据,其中可用于使用downloadTask.cancel(byProducingResumeData: )恢复任务。另请注意,您必须将error强制转换为NSError才能检索userInfo字典。

在使用NSURLSession

之前阅读文档here会很不错