2016-12-16 9 views
-1

新しいデータセットをダウンロードするよう通知する通知メッセージをアプリケーションに送信するバックエンドがあります。ユーザーが通知を受け取ると、アラートボックスはプッシュ通知スレッドで作成され、ユーザーにデータセットのダウンロードを受け入れるか拒否するかを尋ねます。ユーザーがダウンロードを受け入れると、非同期でデータがダウンロードされます。私がしたいのは、ダウンロードが完了したらテーブルビューを更新したいのです。しかし私は別のスレッド上にあり、そのスレッドからテーブルビューを更新する方法がわかりません。それ、どうやったら出来るの?別のスレッドから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スレッドではなく、私はダウンロードを呼び出すときではない。私は押さえつけの糸についている。補完ハンドラを渡すと、UIからではなくプッシュ通知スレッドからのものになります。私は2つのビューを持っています(1つはテーブルビューで、もう1つはUIViewControllerです)。プッシュ通知が受信されると、ユーザはどちらか一方にいる可能性があります。だから私はUIViewController上にいる場合、テーブルのデータをリロードしてはいけません。私は混乱しないと思う。

+1

それは同じでした。もう1つの質問は、メインスレッドのテーブルをバックグラウンドスレッドから更新することでした。それはあなたが求めているのと同じことです。 – rmaddy

+0

@rmaddy私は重複としてそれを見ることができません。私がダウンロードを開始すると、私はもうUIスレッドではありません。ダウンロードはプッシュ通知デリゲートから呼び出されます。 UIスレッドではなく、プッシュ通知デリゲートのバックグラウンドスレッドです。 – user30646

+0

だからこそ、それは重複している。もう1つの問題は同じことをしていました - バックグラウンドスレッドでいくつかのコードを実行し、メインスレッドでUIを更新する必要がありました。答えは、メインスレッドのテーブルをバックグラウンドスレッドから更新する方法を示しました。それだけであなたがする必要があります。 – rmaddy

答えて

1

代わりに、あなたはこのように、メインスレッドに切り替え、バックグラウンドスレッドからあなたのUIを更新しない:...

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

かを

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

+1

質問はスウィフト3ではなく、スウィフト2のコードにあります。 – rmaddy

+0

これは機能しません。ダウンロードスレッドは別のクラスの内部にあるためです。 TableViewControllerクラスの内部にはありません。 – user30646

2

テーブル・ビュー・コントローラーのようなUIオブジェクトは、バックグラウンド・スレッドから更新してください。これは明示的に禁止されています。

あなたがしたいことは、完了ハンドラをとるダウンロードマネージャクラス(それがクラスの場合)に関数を書き込むことです。ダウンロードが完了したら、完了ハンドラを呼び出すようにdownloadContent関数を記述します。私は、正確にこの手法を示すAsync_demo(リンク)と呼ばれるGithubのサンプルプロジェクトを持っています。 (このプロジェクトは、あなたが今スウィフト3がリリースされていることスウィフト3.なぜあなたはスウィフト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がメインスレッドへのGCD呼び出しでラップされた完了ハンドラでUI呼び出しを行うことが何を意味するのか理解していないことは明らかでした。あなたが参照したもう1つのスレッドは、バックグラウンドスレッドでの作業の処理方法と、メインスレッドへのUI更新の送信方法については説明していませんでした。 –

+0

私はAmazonMobileClientとの統合を決定するまでSwift 3を使用していました。それはSwift 3をサポートしていません。とにかく、私はSwiftにはまだまだ新しく、あなたの答えを混乱させます。ダウンロードマネージャクラス内のこのダウンロード機能は、AmazonPushNotificationManagerを実装するクラスから呼び出されます。プッシュ通知を受信すると呼び出されます。だから、私がダウンロードを呼び出すとき、私はもうメインスレッドにはいません。私は押さえつけの糸についている。私は明確にするために自分の投稿を更新しました。 – user30646

関連する問題