【问题标题】:Swift, NSOperationQueue.mainQueue(): update data in operation during operation is running?Swift, NSOperationQueue.mainQueue(): update data in operation during operation is running?
【发布时间】:2014-10-17 18:19:24
【问题描述】:

我在IOS项目中使用后台文件下载,当文件下载开始时,进度视图的更新是通过block NSOperationQueue.mainQueue().addOperationWithBlock()在方法中开始的:

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    if totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown {
       println("Unknown transfer size");
    }
     else{
       let data = getDBInfoWithTaskIdentifier(downloadTask.taskIdentifier)

       NSOperationQueue.mainQueue().addOperationWithBlock(){
           data.db_info.downloadProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
            let inf = data.db_info.indexPath
            let cell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: data.index, inSection: 0)) as SettingsTableViewCell
            cell.downloadProgress.hidden = false
            cell.downloadProgress.setProgress(data.db_info.downloadProgress, animated: true)
        }
    }
}

当带有下载 UI 的视图被关闭并再次出现时,self.tableView 是新对象,但在 NSOperationQueue.mainQueue() 操作中更新进度视图的 self.tableView 是旧对象,即关闭之前的内容。 Println() 返回两个不同的对象。 NSOperationQueue.mainQueue() 块中是否有可能更新有关 self.tableView 的数据?

【问题讨论】:

    标签: ios xcode swift nsoperationqueue


    【解决方案1】:

    首先,您应该考虑切换到 GCD(Grand Central Dispatch)。

    出现您的问题是因为在闭包中捕获了对 tableView 的引用。您可以考虑将逻辑放在一个单独的类函数中,这样tableView 就不会在您的闭包中公开。它还有一个额外的好处是代码更清晰、更有条理。

    这是一个总体思路:

    // new function
    func setProgressInCell (data:?) { // '?' because i do not know the type
        let inf = data.db_info.indexPath
        let cell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: data.index, inSection: 0)) as SettingsTableViewCell
        cell.downloadProgress.hidden = false
        cell.downloadProgress.setProgress(data.db_info.downloadProgress, animated: true)
    
    }
    
    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        if totalBytesExpectedToWrite == NSURLSessionTransferSizeUnknown {
           println("Unknown transfer size");
        }
         else{
           let data = getDBInfoWithTaskIdentifier(downloadTask.taskIdentifier)
    
           dispatch_async(dispatch_get_main_queue())  {
               [weak self] in
               data.db_info.downloadProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
               self.setProgressInCell(data)
    
            }
        }
    }
    

    【讨论】:

    • 我发现了为什么它有旧的self.tableView,这是因为后台会话仍然将视图视为委托,而不是新的,我不知道是否可以更新 NSURLSession 委托或不是。即使使用您的代码,URLSession 也会处理已关闭的视图,并且与新呈现的视图无关。
    猜你喜欢
    • 2022-12-27
    • 2022-12-28
    • 2022-10-15
    • 2022-12-02
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多