【问题标题】:Updating UI Dispatch_Async background download Swift更新 UI Dispatch_Async 后台下载 Swift
【发布时间】:2015-07-30 18:58:36
【问题描述】:

我正在开发一个文件夹/文件应用程序,用户可以在其中将文件下载到本地磁盘。每当用户下载文件时,我想显示一个显示进度的下载栏。

为此,我创建了一个协议,允许我的下载类和我的视图控制器进行通信:

协议:

protocol DownloadResponder : class {
    func downloadFinished()
    func downloadProgress(current:Int64, total:Int64)
}

下载类:

class fileDownloader: NSObject, NSURLSessionDelegate, NSURLSessionDownloadDelegate {

    //responder
    var responder : MyAwesomeDownloadResponder?

    init(responder : MyAwesomeDownloadResponder) {
        self.responder = responder
    }

    ...

    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {

        println("downloaded \(100*totalBytesWritten/totalBytesExpectedToWrite)")
        responder?.downloadProgress(totalBytesWritten, total: totalBytesExpectedToWrite)

    }

...

}

然后在我的视图控制器中,我有一个触发downloadProgress 功能的下载按钮:

func downloadProgress(current:Int64, total:Int64) {
        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
        dispatch_async(dispatch_get_global_queue(priority, 0)) {
            // do some task
            var currentProgress = 100 * current / total
            dispatch_async(dispatch_get_main_queue()) {
                // update some UI
                self.downloadLbl.text = "Downloaded \(currentProgress)%"
                //set progress bar
                self.progressBar.setProgress(Float(currentProgress), animated: true)
            }
        }

    }

虽然控制台中的打印信息一直有效,但更新 UI 并不是很稳定。为了解决这个问题,我使用了在主线程上推送 UI 更改的 dispatch_async 方法。然而,虽然它总是第一次工作,弹回前一个视图控制器并再次返回,再次执行下载不会触发 UI 更新。进度条progressBar.setProgress 什么都不做,我的标签downloadLbl.text 不会自行更新。

有人知道解决这个问题的方法吗? 如果我的问题缺少信息,请告诉我,我会尝试补充现有信息。谢谢!

【问题讨论】:

    标签: ios swift user-interface dispatch-async background-thread


    【解决方案1】:

    由于我没有收到/找到任何问题的解决方案,我回到了更高的级别并更改了我的类之间的通信方式,以根据后台下载线程进程处理 UI 更改。

    我没有使用协议,而是选择了通知,它解决了我的问题。

    下载类内部:

    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    
            println("downloaded \(100*totalBytesWritten/totalBytesExpectedToWrite)")
    
            //NOTIFICATION
            // notify download progress!
            var fileInfo = [NSObject:AnyObject]()
            fileInfo["fileId"] = fileDownloader.storageInfo[downloadTask.taskIdentifier]!["id"] as! Int!
            fileInfo["fileCurrent"] = Float(totalBytesWritten)
            fileInfo["fileTotal"] = Float(totalBytesExpectedToWrite)
    
            let defaultCenter = NSNotificationCenter.defaultCenter()
            defaultCenter.postNotificationName("DownloadProgressNotification",
                object: nil,
                userInfo: fileInfo)
    
        }
    

    在视图控制器内部:

    override func viewDidLoad() {
            super.viewDidLoad()
    
            // ready for receiving notification
            let defaultCenter = NSNotificationCenter.defaultCenter()
            defaultCenter.addObserver(self,
                selector: "handleCompleteDownload:",
                name: "DownloadProgressNotification",
                object: nil)
        }
    
    func handleCompleteDownload(notification: NSNotification) {
            let tmp : [NSObject : AnyObject] = notification.userInfo!
    
            // if notification received, change label value
            var id = tmp["fileId"] as! Int!
            var current = tmp["fileCurrent"] as! Float!
            var total = tmp["fileTotal"] as! Float!
            var floatCounter = 100 * current / total
            var progressCounter = String(format: "%.f", floatCounter)
    
            if(id == self.fileId){
                let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
                        dispatch_async(dispatch_get_global_queue(priority, 0)) {
                            // do some task
                            dispatch_async(dispatch_get_main_queue()) {
                                // update some UI
                                self.downloadLbl.text = "Downloaded \(progressCounter)%"
                                self.progressBar.setProgress((progressCounter as NSString).floatValue, animated: true)
                            }
                        }
            }
        }
    

    希望对您有所帮助!

    【讨论】:

    • 嘿@skynine 你能提供完整的源代码吗??
    • 算了,正在找
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多