当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)
}
当URLSessionDownlaodTask
为nil
时,它可以正常工作,但是当任何下载开始时,它会在保存时崩溃。
scenerio:
我使用所有属性初始化了我的自定义类对象,但将task设置为nil。
我将该对象存储在它保存完好的核心数据中。
我初始化该对象的任务,下载工作完美。
然后我更新核心数据中的对象,同时更新应用程序崩溃,因为URLSssionTask不是从NSCoding继承的。所以它没有编码和解码方法。
我想要一些解决方案来解决这个问题
任何帮助将不胜感激。感谢。
答案 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