2017-09-26 13 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) 
}