2017-03-08 9 views
2

이미지 배열을 반복하는 API 여러 개의 사진을 보내려고합니다. 각 이미지를 다른 스레드에서 보내려하지만 주먹 스레드 이 완료되면 스레드의 나머지 부분을 기다리지 않고 하나의 그림 이 전송됩니다.스위프트 3 : 여러 스레드 실행 및 완료 대기

// create the concurrent queue 
    let asyncQueue = DispatchQueue(label: "asyncQueue", attributes: .concurrent) 

    // perform the task asynchronously 
    for image in self.arrayImages{ 
     asyncQueue.async() { 
      let strBase64:String = image.base64EncodedString(options: .lineLength64Characters) 
      self.sendImage(image: strBase64) 
     } 

    } 

나는 최근 스위프트 프로그래밍을 시작했습니다 내가 스레드를 동기화하는 방법을 모른다 :

이 내 코드입니다. 도와 주실 수 있겠습니까? 내 요청을 할

코드는 다음과 같습니다

// Función para mandar a la API la petición de añadir una imagen a la idea 
func sendImage(image:String){ 
    let data = NSMutableDictionary() 

    let id:Int = (idea?.id)! 
    let pasoAct = idea?.pasoActual 
    data["id_idea"] = id 
    data["id_paso"] = pasoAct 
    data["contenido"] = image 

    let jsonData = try! JSONSerialization.data(withJSONObject: data, options: JSONSerialization.WritingOptions(rawValue: 0)) 
    let request = NSMutableURLRequest(url: NSURL(string:"http://192.168.2.101:3001/api/imagen") as! URL) 
    request.httpMethod = "POST" 
    request.addValue("application/json", forHTTPHeaderField: "Content-Type") 
    request.addValue("application/json", forHTTPHeaderField: "Accept") 
    request.httpBody = jsonData 

    URLSession.shared.dataTask(with: request as URLRequest, completionHandler: self.responseImage).resume() 
} 
// Función de control de la respuesta del servidor tras enviar una imagen 
func responseImage(data: Data?, response: URLResponse?, error: Error?) { 

    if (error != nil) { 
     print("No se ha podido contactar con el servidor") 
    } 
    else{ 
     // Connected, check response, GET status codes. 
     let statusCode = (response as! HTTPURLResponse).statusCode 

     switch statusCode{ 
      case 200: 
       print("Imagen subida") 

      default: 
       print("Error en la petición al servidor") 
     } 
    } 
} 

첫 번째 이미지 (응답 = 200 상태 코드를 반환) 제대로 업로드되어 있지만 다음 이미지가 안

이것은 내가했습니다 코드입니다 귀하의 조언 아래 수정 :

귀하의 경우
func sendImage(image:String, completion: @escaping() -> Void) { 

    let data = NSMutableDictionary() 

    let id:Int = (idea?.id)! 
    let pasoAct = idea?.pasoActual 
    data["id_idea"] = id 
    data["id_paso"] = pasoAct 
    data["contenido"] = image 

    let jsonData = try! JSONSerialization.data(withJSONObject: data, options: JSONSerialization.WritingOptions(rawValue: 0)) 
    let request = NSMutableURLRequest(url: NSURL(string:"http://192.168.2.101:3001/api/imagen") as! URL) 
    request.httpMethod = "POST" 
    request.addValue("application/json", forHTTPHeaderField: "Content-Type") 
    request.addValue("application/json", forHTTPHeaderField: "Accept") 
    request.httpBody = jsonData 

    URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in 
     self.responseImage(data: data, response: response, error: error) 

     // When responseImage is complete, call the completion handler 
     completion() 
    } 
} 


// And the following code is called when I try to send the array of images 
let group = DispatchGroup() 
    let asyncQueue = DispatchQueue(label: "asyncQueue", attributes: .concurrent) 
    for image in self.arrayImages { 

     asyncQueue.async { 
      group.enter() 

      let strBase64:String = image.base64EncodedString(options: .lineLength64Characters) 
      self.sendImage(image: strBase64) { 
       group.leave() 
      } 
     } 
    } 

    group.wait() 

답변

1

, 더 나은 수 있습니다 사용하는 concurrentPerform :

DispatchQueue.concurrentPerform(iterations: self.arrayImages.count) { i in 
    let strBase64 = self.arrayImages[i].base64EncodedString(options: .lineLength64Characters) 
    self.sendImage(image: strBase64) 
} 

print("Done") // This line will only be executed after self.send() is 
       // called on all images. However, this does not mean that 
       // the server has received all the images. 
+0

에 동의합니다. 모든 비동기가 기본적으로 동일한 코드를 실행하는 경우, 나는 또한 –

+0

이 나를 위해 작동하지 않았다는 것을 권하고 싶습니다. ( –

1

당신은 DispatchGroup ...

let group = DispatchGroup() 

for image in self.arrayImages { 

    let workItem = DispatchWorkItem(qos: .default, flags: []) { 
     let strBase64:String = image.base64EncodedString(options: .lineLength64Characters) 
     self.sendImage(image: strBase64) 
    } 
    // perform the task asynchronously 
    group.notify(queue: asyncQueue, work: workItem) 
} 

group.wait() 

// Done!! 

EDIT를 사용할 수 있습니다 지금 당신은 당신의 질문을 업데이 트했습니다, 난 당신이 다른 비동기 호출을하고 볼 수 있습니다. 당신은이 다음 것을 처리 할 수 ​​

func sendImage(image:String, completion: @escaping() -> Void) { 

     // Your code here 

     URLSession.shared.dataTask(with: URL()) { (data, response, error) in 
      self.responseImage(data: data, response: response, error: error) 

      // When responseImage is complete, call the completion handler 
      completion() 
     } 

} 

let group = DispatchGroup() 

for image in self.arrayImages { 

    asyncQueue.async { 
     group.enter() 

     let strBase64:String = image.base64EncodedString(options: .lineLength64Characters) 
     self.sendImage(image: strBase64) { 
      group.leave() 
     } 
    } 
} 

group.wait() 

// Done!! 

내가 따라 같은 간단한 규칙이 항상이 에 매개 변수로 내가 쓰는 모든 비동기 FUNC를 완료 처리기를 추가 이다.

+0

이 경우에는 ID가'DispatchQueue.concurrentPerform'을 사용하는 반면이 대답은 일반적인 접근 방식을 나타내는데 가치가 있습니다 –

+0

didn ' 첫 번째 그림이 업로드되면 내 API에 대한 응답이 실패합니다. –

+0

내 이미지를 64Bytes 문자열로 내 API에 보내고 내 API가 요청 엔터티를 throw하기 때문에 요청마다 스레드를 시작해야합니다. 큰 "오류 –