2017-03-19 9 views
-1

私には2つの質問があります。Swift非同期HTTPリクエストは別のスレッドを作成しますか?

最初の1つは「即時非同期http要求が別のスレッドを作成しますか」です。

2番目の問題は、テーブルビューがあり、httpリクエスト後にサーバーから取得したデータに基づいてテーブルビューを更新する必要があることです。しかし、私がself.tableview?.loadDataをdispatch_asyncクロージャの外側で実行すると、動作しません。 (それは長い時間の後に更新されます)。

私の質問はなぜそれが起こるのですか?メインスレッドに戻らずに、そのスレッドだけでテーブルビューをリフレッシュできないのはなぜですか?

私は、しばらくの間、迅速なhttp要求とそのメカニズムの説明を探していました。もし誰かが詳細に説明したいのであれば、本当にありがとう!

私はあなたがスウィフトからNSURLSEssionを呼び出すことができますあなたの質問は、「スウィフト非同期HTTPリクエスト」について、実際にではなく、およそNSURLSession(ORスウィフト3のURLSession

let request = NSMutableURLRequest(URL: NSURL(string: "http://xxx/getAllposts.php")!) 
    request.HTTPMethod = "POST" 
    let postString = "user=ios" 
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding) 
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { 
     data, response, error in 
     if error != nil { 

      print("error=\(error)") 
      return 
     } 

     print("response = \(response)") 
     let responseString = try! NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary 
     if responseString!["success"] as! Int == 0{ 
      return 
     } 

     let array:NSArray = responseString!["all"] as! NSArray 

     dispatch_async(dispatch_get_main_queue()) { [unowned self] in 
      self.values = array 
      self.tableView?.reloadData(); 

     } 
    } 
    task.resume() 
+0

私はこの問題の半分を理解しています。私は最初にHTTPリクエストがバックグラウンドスレッドを作成することを知っています。しかし、それが「非同期要求」としても知られている理由です。他のスレッドは非同期にしましたか? – user5713716

+0

Swift 3では、 'dispatch_async()'の構文が 'DispatchQueue.main.async()'に変更されています。 –

答えて

0

の下に自分の作業コードを添付しています、Objective-Cから、おそらくC++やCから。言語は問題ではありません。

NSURLSession非同期ネットワーク要求をサポートします。つまり、プログラムが実行されている間は、「重い持ち上げ」がバックグラウンドで実行されます。非同期APIはほとんどの場合、バックグラウンドスレッドで作業するように記述されていますが、同じことを行う他の方法があります。 (旧式のハードウェアでは、非同期通信は割り込みなどを使用して処理されることがあります)。NSURLSessionは、共有スレッドのプールを使用して作業を行います。だから、別のスレッドでネットワークトランザクションを行うのですが、その目的のために独自のスレッドを作成することはありません(スレッドの作成は時間とシステムリソースの面でかなりコストがかかります。このような場合に必要に応じて使用してください)。

タスクが完了すると、NSURLSessionは呼び出し元にそのことを通知します。これは、完了ハンドラまたはデリゲートを介して行うことができます。コンプリートメソッドとデリゲートメソッドは両方とも、シリアル操作キューで実行されます。 (いずれの場合もデリゲートキューと呼ばれます)。デフォルトでは、NSURLSessionはその操作キューを作成し、バックグラウンドスレッドで実行されます。デフォルトのNSURLSessionを使用する場合は、デリゲートキューを変更できないと思います。独自のNSURLSessionを作成する場合は、メインスレッドで実行されるディスパッチキューを使用するように設定できますが、推奨しません。バックグラウンドスレッドでデータ処理を行うのは良いことです。

これは、通常、タスクについて送信されたメッセージがバックグラウンドスレッドで送信されることを意味します。

ほとんどのUIKit呼び出しは、メインスレッドで実行する必要があります。そうでない場合、結果は未定義です(UI更新の長い遅延からクラッシュやその他の異常な動作に至るまで)

メインスレッドではtableView.reloadData()のような呼び出しを行う必要があります。だからこそ、あなたはそれを呼び出してラップする必要がありますDispatchQueue.main.async()

+0

本当にあなたの答えに感謝します!非常に包括的!最後の質問tho、私はDispatchQueue.main.async()の外でテーブルビューをリフレッシュしようとしましたが、それはまだ長い時間がかかることを除いてリフレッシュされます。だから私は、バックグラウンドスレッドでtableView.reloadData()を呼び出すのは、メインスレッドに戻ることなくサーバーからデータを取得した直後です。実際にテーブルをリフレッシュする前にそのスレッドの実行が完了するまで待つのでしょうか? – user5713716

+0

この部分を参照してください: "ほとんどのUIKit呼び出しはメインスレッドで実行する必要があります。そうでない場合、結果は未定義です(** UI更新の長時間の遅延から**クラッシュやその他の奇妙なこれはバックグラウンドからのUI更新の症状です。あなたは何が起こるかを確信することはできません。時にはうまくいくこともありますが、ほとんどの場合、何か悪いことが起こります。それをしないでください。彼は腹筋手術をしている間に外科医に開胸手術を施すようなものです。それはうまくいくかもしれないが、患者が間違った時間に動くと、それは非常にひどく終わることがある。 –

+0

清潔! Uはまた、補完ハンドラを使って述べました。私は完了クロージャでUIを更新することでそれを実験しました。そうすれば、UIを更新しようとする前にデータがすべて処理されていることを確認できます。しかし、それは私にUIを更新するのに長い時間がかかる同じ結果をもたらしました。だから、もし私が完了クロージャでもtableviewをリロードしようとすると、それはまだバックグラウンドスレッドでやっていると思いますか? – user5713716

関連する問題