Swift。 运行 在后台异步下载并让用户与 UI 交互

Swift. Running async download in the background and let user interact with UI

正在使用以下函数将应用程序与来自服务器的 json 数据同步,如果内容有一段时间没有更新,这需要几分钟时间。至于现在,该应用程序会阻止主 UI 并告诉用户它正在更新新内容并出现一个纺车。 我想删除 "blocking overlay with updating data.. text and spinning wheel" 并让应用下载 json 并将其同步到后台的数据库,以便用户可以继续与 UI 进行交互。

我尝试使用 dispatch_async,但 UI 一直被阻止,直到更新完成。有人对如何实现这一目标有任何建议吗?

我将代码精简到相关点,并在 ApiWrapper 执行网络作业的地方添加了 updateData 函数。

func syncData(now: Bool) {

    var synced : Bool = false

    if ((NSUserDefaults.standardUserDefaults().objectForKey("lastSyncApp")) != nil) {
        var interval = 0
        if ((NSUserDefaults.standardUserDefaults().objectForKey("intervalSyncValue")) != nil) {
            interval = NSUserDefaults.standardUserDefaults().objectForKey("intervalSyncValue") as! Int
        }
        else{
            interval = 86400
        }
        let date = NSUserDefaults.standardUserDefaults().objectForKey("lastSyncApp") as! NSDate
        var timestamp = UInt64(floor(date.timeIntervalSince1970))
        //Create final date
        let lastsyncTimestampDate : UInt64 = timestamp + UInt64(interval)

        var nowTimestampDate = UInt64(floor(NSDate().timeIntervalSince1970))

        if ((nowTimestampDate > lastsyncTimestampDate) || now) {


                synced = true
                let formatter = NSDateFormatter()
                formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

                //MRProgressOverlayView.showOverlayAddedTo(self.window, title: "Aggiorno dati...", mode: MRProgressOverlayViewMode.Indeterminate, animated: true, tintColor: UIColor.blackColor())

                self.downloadDate = formatter.stringFromDate(date)
                NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateData:"), userInfo: nil , repeats: false)



    ….}        








func updateData(timer: NSTimer!) {


    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
    dispatch_async(dispatch_get_global_queue(priority, 0)) {
        // do some task



    var ApiWrapper = API()

    let date = self.downloadDate


            ApiWrapper.model.deleteNews()
            ApiWrapper.model.resetNewsFetch()



            //var ApiWrapper = API()

…… }

我没有看到您在这段代码中的什么地方使用了后台线程,但是这里非常简洁 example 如何执行此操作。

基本上,

dispatch_async(dispatch_get_global_queue(priority, 0)) {}

会让你进入后台线程,如果你需要从那里更新 UI,请确保你在主线程上执行该代码:

dispatch_async(dispatch_get_main_queue()) {}

Swift 4 更新

DispatchQueue.global(qos: [Desired QoSClass]).async {
    // This code is executing on a background thread at 
    // your desired quality of service level

    DispatchQueue.main.async {
         // Code to be executed on the main thread here
    }
}