2017-09-26 77 views
0

我正在使用swift 3.0並創建了一個返回整數數組的函數。整數數組非常具體,它們從數據庫中獲取,因此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) 
}