2016-12-16 111 views
-1

我有後端發送通知消息到我的應用程序來通知用戶下載新的數據集。當用戶收到通知時,alertbox將在pushnotification線程中創建,並要求用戶接受或拒絕數據集下載。如果用戶接受下載,它將以異步方式下載數據。我想要做的是,我想在下載完成後刷新表格視圖。但我在不同的線程,我不知道如何更新該線程的tableview。我怎麼做?從另一個線程刷新UITableViewController

func downloadContent(key: String, pinOnCompletion: Bool) { 

     let manager = AWSUserFileManager.defaultUserFileManager() 
     let content = manager.contentWithKey(self.prefix + key) 

     content.downloadWithDownloadType(
      .IfNewerExists, 
      pinOnCompletion: pinOnCompletion, 
      progressBlock: {[weak self](content: AWSContent?, progress: NSProgress?) -> Void in 
       guard self != nil else { return } 
       /* Show progress in UI. */ 
      }, 
      completionHandler: {[weak self](content: AWSContent?, data: NSData?, error: NSError?) -> Void in 
       guard self != nil else { return } 
       if let error = error { 
        print("Failed to download a content from a server. \(error)") 
        return 
       } 
       if let fileData = data { 
        // Saves Data to core data here 
        // Update the tableViewController 

       } 
       print("Object download complete.") 
      }) 
    } 

更新-1 這是不重複的帖子。建議的重複帖子詢問如何從tableviewcontroller類中的異步任務更新tableviewcontroller。我的問題是關於從不同類的另一個線程更新tableviewcontroller。

更新-2 只是爲了澄清,下載管理器類這裏面下載功能是從實現AmazonPushNotificationManager類調用。它在接收到推送通知時被調用。所以當我調用下載時,我不在UI線程中。我正在推送通知線程。如果我傳遞完成處理程序,這將來自pushnotification線程,而不是來自UI。我有兩個視圖(一個是tableview,另一個是UIViewController)。當收到推送通知時,用戶可以在任一個上。所以如果用戶在UIViewController上,我不應該重新加載表數據。我希望這聽起來不會令人困惑。

+1

這是一樣的。另一個問題是關於從後臺線程更新主線程上的表。這是你問的同一件事。 – rmaddy

+0

@rmaddy我不認爲它是重複的。當我開始下載時,我不再使用UI線程。從推送通知代理調用下載。它是推送通知委託的後臺線程,而不是UI線程的後臺線程。 – user30646

+0

這就是爲什麼它是重複的。另一個問題是做同樣的事情 - 在後臺線程上運行一些代碼,並需要更新主線程上的UI。答案向你展示瞭如何從後臺線程更新主線程上的表。這正是你需要做的。 – rmaddy

回答

1

你不從後臺線程更新UI,而是你切換回主線程,就像這樣:

dispatch_async(dispatch_get_main_queue()) { self.tableView.reloadData() } (SWIFT 2)

或...

DispatchQueue.main.async { self.tableView.reloadData() }(SWIFT 3)

+1

問題出在Swift 2代碼中,而不是Swift 3. – rmaddy

+0

這不起作用。因爲下載線程在不同的類中。不在TableViewController類內。 – user30646

2

正如其他人所說,你像從後臺線程表視圖控制器更新UI對象。這是明確禁止的。

你想要做的是在你的下載管理器類中編寫一個函數(如果這是類的話),它需要一個完成處理程序。編寫downloadContent函數,以便在下載完成後調用完成處理程序。我在Github上有一個示例項目,名爲Async_demo(鏈接),它完全演示了這種技術。 (?這個項目是用斯威夫特3.此時,您應在斯威夫特3.做新的開發爲什麼你要問關於SWIFT 2,現在斯威夫特3已經發布)

的關鍵功能是:

/** 
    This function demonstrates handling an async task. 
    - Parameter url The url to download 
    - Parameter completion: A completion handler to execute once the download is finished 
    */ 


func downloadFileAtURL(_ url: URL, completion: @escaping DataClosure) { 

    //We create a URLRequest that does not allow caching so you can see the download take place 
    let request = URLRequest(url: url, 
          cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, 
          timeoutInterval: 30.0) 
    let dataTask = URLSession.shared.dataTask(with: request) { 
    //------------------------------------------ 
    //This is the completion handler, which runs LATER, 
    //after downloadFileAtURL has returned. 
    data, response, error in 

    //Perform the completion handler on the main thread 
    DispatchQueue.main.async() { 
     //Call the copmletion handler that was passed to us 
     completion(data, error) 
    } 
    //------------------------------------------ 
    } 
    dataTask.resume() 

    //When we get here the data task will NOT have completed yet! 
} 

}


+1

你爲什麼重新打開?這和我關閉它一樣。 OP想要從後臺重新加載主線程上的表。這是另一個問題提出並回答的問題。這和你的答案一樣。 – rmaddy

+0

@rmaddy,我很清楚,OP不明白在完成處理程序中執行UI調用意味着什麼,這個完成處理程序包含在對主線程的GCD調用中。您引用的另一個線程沒有解釋如何處理後臺線程的工作,然後將UI更新發送到主線程,我決定使用明確的解釋。 –

+0

我正在使用Swift 3,直到我決定與AmazonMobileClient集成。它不支持Swift 3.無論如何,我還是Swift的新手,我對你的回答感到困惑。因此,下載管理器類中的此下載功能是從實現AmazonPushNotificationManager的類中調用的。它在接收到推送通知時被調用。因此,當我調用下載時,我不再處於主線程中。我正在推送通知線程。我更新了我的帖子以澄清。 – user30646