簡體   English   中英

Swift:UIViewController 實例未從 URLSession 委托方法接收更新

[英]Swift: UIViewController instance not receiving updates from URLSession Delegate methods

我無法從 URLSession Delegate 方法更新 UIViewController。

我有一個包含不同用戶的 TableView 和一個包含與該用戶關聯的多個圖像的詳細視圖 controller。

現在我需要下載圖像,我創建了一個背景 URL session,每個用戶都有一個唯一標識符。 我這樣做是因為我必須為 TableView 中的每個用戶使用相同的詳細信息 UIViewController。

> 細節視圖控制器

// Download service for this controller. Shared instance because it tracks active downloads. /// [URL:Download]

let downloadService:DownloadService = MediaDownloadManager.shared.downloadService


// A Unique background download session for each user

lazy var downloadSession: URLSession = {
    let identifer:String = "com.example.app" + "-user-" + userID   /// userID passed from parent
    let configuration = URLSessionConfiguration.background(withIdentifier: identifer)
    return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}()


override func viewDidLoad() {
    super.viewDidLoad()
    downloadService.downloadsSession = downloadSession

    /// I get this every time when I exit and re-enter the controller which is obvious.
    /// [DEBUG CONSOLE] A background URLSession with identifier com.example.app-user-12 already exists!
}

為了跟蹤下載進度和更新視圖,我已將 URLSession Delegates 與我的 DetailViewController 保持一致。

extension DetailViewController: URLSessionDelegate, URLSessionDownloadDelegate {
    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { /// }
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { /// }
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { /// }
}

現在的問題是,當我運行應用程序並為用戶打開 DetailViewController 並開始下載我需要的圖像時,它工作正常,我從 urlsession 委托方法獲取更新,然后更新我的 tableView。

但是當我滑回 TableViewController 然后為同一用戶重新打開 DetailViewController 並開始下載圖像時,DetailViewController 的 tableView 不會從這些 urlsession 委托方法接收更新。

我找到了導致這個問題的確切原因。 URLSession Delegate 方法捕獲我的視圖 controller 的實例。 這意味着當我從 URLSession Delegate 方法更新我的 DetailViewController 的 TableView 時,他們實際上嘗試更新第一個和以前的 UIViewController 實例的 tableView。

下面是更新單元格進度的代碼。

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    guard let downloadURL = downloadTask.originalRequest?.url else {
        printAndLog(message: "### \(#function) Failed to retrieve original request download url", log: .network, logType: .error)
        return
    }
    let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
    let downloadedSize = ByteCountFormatter.string(fromByteCount: totalBytesWritten, countStyle: .file)
    let totalSize = ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file)

    print(self) /// Same instance everytime.

    if let download = downloadService.activeDownloads[downloadURL] {
        download.progress = progress
        DispatchQueue.main.async {
            if let index = self.images.firstIndex(of: download.image),
                let cell = self.tableView.cellForRow(at: IndexPath(row: index, section: 0)) as? ImageCell {
                cell.updateProgress(progress: download.progress, loadedSize: downloadedSize, totalSize: totalSize)
            }
        }
    }
}

我該如何解決這個煩人的問題? 我知道單身人士是一個很好的答案,但我想盡可能避免單身人士。

我不能使用downloadSession.finishTasksAndInvalidate()因為我認為當我退出 controller 時它不會繼續我的下載。

我的要求:

1-) 當我退出 controller 時,應該會繼續下載。

2-) DetailViewController 的每個實例(即每個用戶)都應該可以下載

3-) 后台下載當然是必須的。

如果您認為這個問題的標題是錯誤的,請原諒。

您需要添加另一個抽象級別。 視圖不應直接訂閱后台下載過程。 其他一些 class 應該訂閱它,並且應該從其他 class 更新視圖。

這樣,即使多個視圖需要數據,您也只有一次 class 訂閱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM