Swift3 同步发送多个URLSession dataTask请求并等待结束

Swift3 同步发送多个URLSession dataTask请求并等待结束,swift3,urlsession,nsurlsessiondatatask,Swift3,Urlsession,Nsurlsessiondatatask,我需要向服务器发送多个POST请求,但在执行此操作时遇到了同步问题 我需要做以下工作: 显示进度条(正在下载…) 发送第一个POST请求 每发送n张图片 发送图片 结束 发送每篇文章时,禁用进度条 显示状态弹出消息 以下是我使用的代码: 调用第一个POST请求的func self.envoi{ (response) in if let result = response as? Bool { if(result == true){ //now we are sending th

我需要向服务器发送多个POST请求,但在执行此操作时遇到了同步问题

我需要做以下工作:

  • 显示进度条(正在下载…)
  • 发送第一个POST请求
  • 每发送n张图片
    • 发送图片
  • 结束
发送每篇文章时,禁用进度条 显示状态弹出消息

以下是我使用的代码:

  • 调用第一个POST请求的func

    self.envoi{ (response) in
    if let result = response as? Bool {
    if(result == true){
        //now we are sending the Photos !
        var i = 0;
        while(i <      selectedPictures.sharedInstance.selectedCells.count){
            self.envoiPhoto(obj: PhotoGallery.sharedInstance.photoGallery[item], pic: self.Image, num: item){ (result) -> () in
                    print("Envoi Photo \(i): \(result)")
            }
            i=i+1;
        }//end loop while for each pic
    
        print("we have sent all the pictures")
    
        alertController.dismiss(animated: true, completion: ({
        }))
        self.envoiSuccess()
    }
    else{
        print("erreur d'envoi")
        self.envoiError()
    }
    }
    }
    
    第二张func环境照片:

        func envoiPhoto(obj: Photo, pic: UIImage, num: Int, completion: @escaping (_ result: Bool)->()){
    
        let url = URL(string: "\(KAIROS_SERVER)/MobileCreatePhoto")
        var request = URLRequest(url: url!)
        request.httpMethod = "POST"
        let boundary = self.generateBoundaryString()
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
        let image_data = UIImagePNGRepresentation(self.fixOrientation(img: self.constatImage))
    
        let body = NSMutableData()
    
        //preparing values for pictures
        let fname = "Constat-\(reference!)-\(num).png"
        let mimetype = "image/png"
        let CRLF = "\r\n";
    
        //send parameter id
        body.append("--\(boundary)\(CRLF)".data(using: String.Encoding.utf8)!)
        body.append("Content-Disposition: form-data; name=\"id\"\(CRLF)".data(using: String.Encoding.utf8)!)
        body.append("Content-Type: text/plain; charset=UTF-8\(CRLF)\(CRLF)".data(using: String.Encoding.utf8)!)
        body.append("\(id!)\(CRLF)".data(using: String.Encoding.utf8)!)
    
        body.append("--\(boundary)\(CRLF)".data(using: String.Encoding.utf8)!)
        body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(fname)\"\(CRLF)".data(using: String.Encoding.utf8)!)
        body.append("Content-Type: \(mimetype)\(CRLF)\(CRLF)".data(using: String.Encoding.utf8)!)
        body.append(image_data!)
    
        body.append("\(CRLF)".data(using: String.Encoding.utf8)!)
    
        body.append("--\(boundary)--\(CRLF)".data(using: String.Encoding.utf8)!)
    
        request.httpBody = body as Data
    
        let configuration = URLSessionConfiguration.default
        let session = Foundation.URLSession(configuration: configuration,
                                            delegate: self,
                                            delegateQueue:OperationQueue.main)
    
        let task = session.dataTask(with: request, completionHandler: {
            (
            data, response, error) in
    
            guard let _:Data = data, let _:URLResponse = response, error == nil else {
                print("error")
                completion(false)
                return
            }
    
            var id = "0";
            var result = "";
            // Print out response string
            //print("response -- \(response)")
            if let response = response as? HTTPURLResponse {
                if response.statusCode == 200 {
                    print("Create Photo Success")
                }
                id = response.allHeaderFields["id"]! as! String
                print("ID Photo created: \(id)");
                result = response.allHeaderFields["result"]! as! String;
                print("Result: \(result)");
            }
            completion(true)
    
        })
        task.resume() 
    }
    
    今天我主要关心的是确保在向最终用户显示进度条时同步发送每个HTTP POST。 当第一个HTTP POST和每个发送图片的HTTP POST完成时,我需要禁用进度条并显示另一个详细说明操作的alertView

    到今天为止,这些操作尚未同步,即使操作尚未完成,代码也会尝试禁用进度条。 照片上传的启动是在第一次HTTP POST之后启动的(因为它在回调中启动),但由于我需要为每个要发送的图片实现一个循环,我不知道如何在不阻塞URLSession数据任务的情况下同步每个上传(如果我使用DispatchGroup,则是这种情况)

    任何帮助都将不胜感激

    ------------------------------------------------------------------------- 编辑1

    我试图在代码中实现DispatchGroup,但没有按预期同步任何内容

    代码如下:

                var myGroup = DispatchGroup();
    
            self.docSent = false;
            self.allPhotosSent = false
            self.myGroup.enter()
            print("First sending the doc")
    
            self.envoi{ (response) in
                if let result = response as? Bool {
                    if(result == true){
                        self.docSent = true
                        print("Doc sent, now sending photos")
    
                        //now we are sending the Photos !
                        for it in selectedPictures.sharedInstance.selectedCells{
                            print("Sending selected pic item:\(it.item)");
                            print("retrieving picture: \(fileName!)")
                            self.constatImage = self.getSavedImage(named: fileName!)!                            
                            self.envoiPhoto(obj: PhotoGallery.sharedInstance.photoGallery[it.item], pic: self.Image, num: it.item){ (result) -> () in
                                print("Envoi Photo \(it.item): \(result)")
                                if(it.item == selectedPictures.sharedInstance.selectedCells.count-1){
                                    self.allPhotosSent = true
                                }
                            }
                        }
                    }
                    //Case when doc sending is failed
                    else{
                        self.docSent = false
                    }
    
                }
            }//end envoi doc
            self.myGroup.leave()
    
            self.myGroup.notify(queue: .main, execute: {
                print("entering in notify")
                print("we have sent all the pictures")
                if(self.docSent && self.allPhotosSent){
                    //now we need to leave the progress bar...
                    alertController.dismiss(animated: true, completion: ({
                        print("now the alert is dismissed !")
                        self.envoiSuccess()
                    }))  
                }
                else{
                    print("erreur d'envoi de doc")
                    alertController.dismiss(animated: true, completion: ({
                        print("now the alert is dismissed !")
                        self.envoiError()
                    }))
                }
    
            })
    
    以及日志:

    First sending the doc
    entering in notify
    we have sent all the pictures
    erreur d'envoi de doc
    Result: success
    doc sent, now sending photos
    Sending selected pic item:0
    retrieving picture: IMG_0241
    Sending selected pic item:1
    retrieving picture: IMG_1265
    now the alert is dismissed !
    Result: success
    Envoi Photo 0: true
    Result: success
    Envoi Photo 1: true
    

    当然,我错过了一些东西,因为GCD似乎没有像我期望的那样工作。

    不要等待。使用
    DispatchGroup
    在最后一个请求完成时获得通知。在Swift-never
    while
    线性索引循环中,我需要使用什么来代替while?一个
    for-in
    循环
    First sending the doc
    entering in notify
    we have sent all the pictures
    erreur d'envoi de doc
    Result: success
    doc sent, now sending photos
    Sending selected pic item:0
    retrieving picture: IMG_0241
    Sending selected pic item:1
    retrieving picture: IMG_1265
    now the alert is dismissed !
    Result: success
    Envoi Photo 0: true
    Result: success
    Envoi Photo 1: true