2017-09-26 21 views
0

swift 3.0を使用していて、整数の配列を返す関数を作成しました。 Integerの配列は非常に特殊で、データベースから取得されるため、HTTP呼び出しは非同期です。これは3つの異なるコントローラで使用するので関数ですので、一度書くと意味があります。私の問題は、非同期コードがreturn文の後ろに返されるため、nilを返していることです。私はここでこの例を試しましたWaiting until the task finishesしかし、私は値を返す必要があるため主に動作していません。これは私のコードiOS swift戻り値が必要な関数内で非同期タスクを待つ方法

func ColorSwitch(label: [UILabel]) -> [Int] { 

    for (index, _) in label.enumerated() { 
     label[index].isHidden = true 
    } 

    // I need the value of this variable in the return 
    // statement after the async is done 
    var placeArea_id = [Int]() 

    let urll:URL = URL(string:ConnectionString+"url")! 

    let sessionn = URLSession.shared 
    var requestt = URLRequest(url: urll) 
    requestt.httpMethod = "POST" 


    let group = DispatchGroup() 
    group.enter() 

    let parameterr = "http parameters" 
    requestt.httpBody = parameterr.data(using: String.Encoding.utf8) 
    let task = sessionn.dataTask(with:requestt, completionHandler: {(data, response, error) in 
     if error != nil { 
      print("check check error") 
     } else { 
      do { 

       let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any] 
       DispatchQueue.main.async { 

        if let Profiles = parsedData?["Results"] as? [AnyObject] { 
         if placeArea_id.count >= 0 { 
          placeArea_id = [Int]() 
         } 

         for Profiles in Profiles { 

          if let pictureS = Profiles["id"] as? Int { 
           placeArea_id.append(pictureS) 
          } 
         } 
        } 
        group.leave() 
       } 

      } catch let error as NSError { 
       print(error) 

      } 
     } 
    }) 
    task.resume() 


    group.notify(queue: .main) { 
    // This is getting the value however can't return it here since it 
    // expects type Void 
    print(placeArea_id) 

    } 
    // this is nil 
    return placeArea_id 

} 

私はすでに確認され、現在はただの提案は素晴らしいことだ、それを返すために必要な値は、非同期コードの内部で戻ってきています。

答えて

4

これにはクロージャを使用するか、関数を同期させることができます。

func ColorSwitch(label: [UILabel], completion:@escaping ([Int])->Void) { 
    completion([1,2,3,4]) // when you want to return 
} 

ColorSwitch(label: [UILabel()]) { (output) in 
    // output is the array of ints 
    print("output: \(output)") 
} 

ここで閉鎖http://goshdarnclosuresyntax.com/

+0

@Pabloprez屋心配を – Asleepace

4

についてかなり良いブログは、あなたが本当にあなたの関数は、その関数内で非同期操作から値を返すことはできませんです。それは非同期性の目的を破るでしょう。そのデータをColorSwitch(label:)関数の外に戻すには、完了時に呼び出されるクロージャを受け入れるようにする必要があります。このクロージャは、パラメータとして[Int]を受け入れます。あなたのメソッドの宣言はこのような何かを見てする必要があります:

後で
func ColorSwitch(label: [UILabel], completion: @escaping ([Int]) -> Void) -> Void { 

    for (index, _) in label.enumerated() { 
     label[index].isHidden = true 
    } 

    var placeArea_id = [Int]() 

    let urll:URL = URL(string:ConnectionString+"url")! 

    let sessionn = URLSession.shared 
    var requestt = URLRequest(url: urll) 
    requestt.httpMethod = "POST" 


    let group = DispatchGroup() 
    group.enter() 

    let parameterr = "http parameters" 
    requestt.httpBody = parameterr.data(using: String.Encoding.utf8) 
    let task = sessionn.dataTask(with:requestt, completionHandler: {(data, response, error) in 
     if error != nil { 
      print("check check error") 
     } else { 
      do { 

       let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any] 
       DispatchQueue.main.async { 

        if let Profiles = parsedData?["Results"] as? [AnyObject] { 
         if placeArea_id.count >= 0 { 
          placeArea_id = [Int]() 
         } 

         for Profiles in Profiles { 

          if let pictureS = Profiles["id"] as? Int { 
           placeArea_id.append(pictureS) 
          } 

         } 
        } 
        group.leave() 
        completion(placeArea_id) // This is effectively your "return" 
       } 

      } catch let error as NSError { 
       print(error) 

      } 

     } 

    }) 
    task.resume() 
} 

、あなたはこのようにそれを呼び出すことができます。

ColorSwitch(label: []) { (ids: [Int]) in 
    print(ids) 
} 
関連する問題