2017-01-19 15 views
8

以下のコードを使用して、サーバーとデータを同期しています。タスクを完了した後、私は呼び出すしたいと思います:Swift 3.0の補完ハンドラー

self.refreshControl?.endRefreshing() 

しかし、私はそれがこのメソッドの内部で起こるかもしれないものの後に起こることを確認したいと思います。これは私が補完ハンドラを使う場所ですか? httpレスポンスを取得した後に実行されるコードをすでに実行しているので、私は混乱します。補完ハンドラを追加すると、http応答を受け取った後で実行されますか?下のコードで何か起こった後に起こるendRefreshing()コードをそこに置くことができますか? ありがとう!

func syncCustomers(token: String) { 
    let url:NSURL = NSURL(string: Constants.Api.BaseUrl + "api/customer")! 
    let session = URLSession.shared 
    let request = NSMutableURLRequest(url: url as URL) 
    request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") 
    request.httpMethod = "GET" 
    let task = session.dataTask(with: request as URLRequest) { (data, response, error) in 
     guard let data = data else { return } 
     do { 
      if error != nil { 
       self.showAlert(title: "Error", message: error!.localizedDescription) 
      } 
      else if let httpResponse = response as? HTTPURLResponse { 
       if httpResponse.statusCode == 200 { 
        let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? Array<Any> 
        DispatchQueue.global().async { 
         for item in json! { 
          if let customer = Customer(json: item as! [String : Any]) { 
           _ = SqliteDB.instance.replaceCustomer(customer: customer) 
          } 
         } 
         self.customers = SqliteDB.instance.getCustomers() 
         self.tableView.reloadData() 
        } 
       } else if httpResponse.statusCode == 401 { 
        self.showAlert(title: "Error", message: "Unauthorized. Please try logging in again.") 

       } 
      } 
     } catch let error as NSError { 
      self.showAlert(title: "Error", message: error.localizedDescription) 
     } 
    } 
    task.resume() 
} 

答えて

21

完了または閉鎖は、パラメータに包まだけの機能である...

あなたはそう...

func doSomethingAsync(completion:() ->()) { 
} 

のような閉鎖とパラメータcompletionを関数を作成することができます() ->()のタイプです。つまり、入力パラメータ()を使用せず、void ()を返す関数->です。

また、機能のような...

// (inputs) -> (outputs) 
(String) ->() 

それともあなたが望む任意の入力または出力とを作ることができます。

あなたの質問にお答えください。この機能は、他の非同期メソッドは他のメソッドの完了の内側に置く行われた後で完了が呼び出されたことを確認するために...

func myAsyncFunction(completion:() ->()) { 

    someOtherAsyncFunction() { 

     // This is the completion of "someOtherAsyncFunction" 

     // Call YOUR completion here... 
     completion() 
    } 

} 

をいくつかの他の非同期機能を呼び出すことができます。上記のように。

他の非同期メソッドが終了した後今、

self.myAsyncFunction() { 
    // your completion block code here. 
} 

...あなたが行うことができ、これを呼び出すためのあなたの完了ブロックコードは、現在呼び出されます。もちろん

、あなたが(エラーなどのような...)他の補完で複数のパスを持っているならば、あなたは、各エンドポイントであなたの完了を呼び出す必要があります...

func myAsyncFunction(completion:() ->()) { 

    someOtherAsyncFunctionWithAPossibleError() { 
     error in 

     if error != nil { 
      completion() 
      // this return means the other completion won't be run 
      return 
     } 

     completion() 
    } 

} 
+0

感謝。特に、どのように私は各パスの最後に完了を呼び出す必要があるか説明します。 – Primico

+0

@Primico心配する必要はありません。お力になれて、嬉しいです。 – Fogmeister

+0

@Primico、こんにちは、完了はdataTaskでどのように機能しますか?あなたはこの質問(http://stackoverflow.com/questions/43663416/calling-completionhandler-with-firebase)で私を助けることができますか? Tks – Cauca

10
  1. の作成完了ブロック。偉大な説明のための

    func getDataFromJson(url: String, parameter: String, completion: @escaping (_ success: [String : AnyObject]) -> Void) { 
    
        //@escaping...If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is @escaping. 
    
        var request = URLRequest(url: URL(string: url)!) 
        request.httpMethod = "POST" 
        let postString = parameter 
    
        request.httpBody = postString.data(using: .utf8) 
        let task = URLSession.shared.dataTask(with: request) { Data, response, error in 
    
         guard let data = Data, error == nil else { // check for fundamental networking error 
    
          print("error=\(error)") 
          return 
         } 
    
         if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors 
    
          print("statusCode should be 200, but is \(httpStatus.statusCode)") 
          print(response!) 
          return 
    
         } 
    
         let responseString = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String : AnyObject] 
         completion(responseString) 
    
    
    
        } 
        task.resume() 
    } 
    
  2. Callメソッド

    getDataFromJson(url: "http://www.windmillinfotech.com/carlife/carlife_api/automotive_product_list", parameter: "vehicle_type=Car", completion: { response in 
         print(response) 
    
        }) 
    
+1

ありがとう! –