URLSession-background-downloadTask回调中的RealmSwift更新

时间:2018-02-28 22:28:22

标签: swift object realm urlsession

使用Swift-4.0.3,RealmSwift-3.0.2,iOS-11.2.6和Xcode-9.2

我尝试通过URLSession回调(didFinishDownloadingTo)更新Realm对象 - 请参阅下面的代码。多次输入此回调,直到完成文件的完整下载。为了保持下载状态的持久信息,我想使用领域对象。

出于某种原因,这还不行。我得到以下异常:

Main Thread Checker: UI API called on a background thread: -[UIProgressView progress]
PID: 7200, TID: 113132, Thread name: (none), Queue name: NSOperationQueue 0x60000023e8a0 (QOS: UNSPECIFIED), QoS: 0
Backtrace:
4

有什么问题? (另外,调度到主队列或后台没有帮助)!

extension DetailDBFileDownloaderViewController: URLSessionDownloadDelegate {

    let downloadService = MyDownloadService()

    //... not all needed delegate-methods shown....

    // delegete method firing every time another chunk of a large-file has been downloaded...
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {

        // ...

        let tempDownloadEntry = DownloaderItem()    
        tempDownlaodEntry.identifier = self.someID
        tempDownloadEntry.someProperty = self.somePoperty
        tempDownloadEntry.DBFile.index = self.someOtherID
        tempDownlaodEntry.DBFile.moreProp = self.someotherProperty
        // ...    

        let entryRealm = try? Realm()

        if let rlm = entryRealm {

            let predicate = NSPredicate(format: "title == %@", self.titleLabelString!)
            let myTitles = rlm.objects(DownloaderTitleSet.self).filter(predicate)
            if (myTitles.count == 0) {
                // !!!! FIRST ROUND WORKS (i.e. Realm still empty) !!!!
                rlm.beginWrite()
                let newTitleSet = DownloaderTitleSet()
                newTitleSet.title = self.titleLabelString!
                newTitleSet.version = self.versionLabelString ?? "0.0.0"
                newTitleSet.lastItemIndex = self.someID
                newTitleSet.downloaderItems.append(tempDownloadEntry)
                rlm.add(newTitleSet, update: true)
                try! rlm.commitWrite()
            } else if (myTitles.count == 1) {
                // !!!! SECOND, THIRD, etc. round does not work !!!!!!!
                rlm.beginWrite()
                let existingTitleSet = myTitles.first

                // !!!!! Here is where the exception happens !!!!!!!!
                existingTitleSet?.title = self.titleLabelString!
                existingTitleSet?.version = self.versionLabelString ?? "0.0.0"
                existingTitleSet?.lastItemIndex = self.someID
                existingTitleSet?.downloaderItems.append(tempDownloadEntry)
                rlm.add(existingTitleSet!, update: true)
                try! rlm.commitWrite()
            }
        }
    }
    //...

在同一个回调方法didFinishDownloadingTo中(最后) - 如果尚未完成完整的文件下载(例如,通过大块文件的块下载,则会启动另一个下载任务)。 ..)。因此,一次又一次地调用回调方法didFinishDownloadingTo!并且对于每次调用 - 我的Realm对象应保持持久 - 添加列表元素......

    // ... the end of the didFinishDownloadingTo callback-method....
    if !allFileChunksDownloaded() {
        self.downloadService.startDownload(file: file, bytesRange: byteRangeString)
    }
}

这就是三个领域对象的样子:

class DownloaderTitleSet: Object {

    @objc dynamic var title: String = ""
    @objc dynamic var version: String = ""
    @objc dynamic var lastItemIndex: Int = 0
    var downloaderItems = List<DownloaderItem>()

    override static func primaryKey() -> String? {
        return "title"
    }
}

class DownloaderItem: Object {

    @objc dynamic var identifier: String = ""
    @objc dynamic var somePoperty: String = ""
    @objc dynamic var file: DBFile?

    override static func primaryKey() -> String? {
        return "identifier"
    }
}

class DBFile: Object {

    @objc dynamic var index: Int = 0
    @objc dynamic var moreProp: Int = 0

    override static func primaryKey() -> String? {
        return "index"
    }
}

我怎样才能做得更好?

-----有问题的后台任务是一个URLSession-DownloadTask,显示的委托方法来自URLSessionDownloadDelegate回调。

以下代码与RealmSwift-Problem真的无关,我想,但对于对整个图片感兴趣的人 - 这里调用了执行的URLSessionDownload-Task,最终会调用callback-method

// download-Service method starting the background-downloadTask
class MyDownloadService {

    var downloadsSession: URLSession!

    func startDownload(file: MyFile, bytesRange: String) {

        let download = MyDownloadTask(file: file)

        var request = URLRequest(url: file.previewURL!)
        request.httpMethod = "GET"
        request.addValue(file.accountAuthorizationToken!, forHTTPHeaderField: "Authorization")
        download.task = self.downloadsSession.downloadTask(with: request)
        download.task!.resume()
        download.isDownloading = true

        self.activeDownloads[download.file.previewURL!] = download
    }
}

class MyDownloadTask {

  var file: MyFile
  init(file: MyFile) {
    self.file = file
  }

  // Download service sets these values:
  var task: URLSessionDownloadTask?
  var isDownloading = false
  var resumeData: Data?

  // Download delegate sets this value:
  var progress: Float = 0
}

0 个答案:

没有答案