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

时间:2018-09-05 10:25:08

标签: swift3 urlsession nsurlsessiondatatask

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

我需要执行以下操作:

  • 显示进度条(正在下载...)
  • 发送第一个POST请求
  • 每发送n张照片
    • 发送图片n
  • 结束于

每条帖子发送后,禁用进度条 显示状态弹出消息

这是我使用的代码:

  • 调用第一个POST请求的函数

    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 envoi(_ callback: @escaping (Bool) -> ()){

    let url = URL(string: "\(SERVER)/MobileCreate")
    var request = URLRequest(url: url!)
    request.httpMethod = "POST"
    let boundary = generateBoundaryString()
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    let body = NSMutableData()

    let CRLF = "\r\n";

    //send parameter id_user
    body.append("--\(boundary)\(CRLF)".data(using: String.Encoding.utf8)!)
    body.append("Content-Disposition: form-data; name=\"id_user\"\(CRLF)".data(using: String.Encoding.utf8)!)
    body.append("Content-Type: text/plain; charset=UTF-8\(CRLF)\(CRLF)".data(using: String.Encoding.utf8)!)
    body.append("\(User.sharedInstance.id!)\(CRLF)".data(using: String.Encoding.utf8)!)

    //send parameters reference
    body.append("--\(boundary)\(CRLF)".data(using: String.Encoding.utf8)!)
    body.append("Content-Disposition: form-data; name=\"reference\"\(CRLF)".data(using: String.Encoding.utf8)!)
    body.append("Content-Type: text/plain; charset=UTF-8\(CRLF)\(CRLF)".data(using: String.Encoding.utf8)!)
    body.append("\(ref.text!)\(CRLF)".data(using: String.Encoding.utf8)!)

    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")
            callback(false)
            return
        }

        var id = "0";
        var result = "";
        if let response = response as? HTTPURLResponse {
            if response.statusCode == 200 {
                print("Create Success")
            }
            id = response.allHeaderFields["id"]! as! String
            result = response.allHeaderFields["result"]! as! String;
            print("Result: \(result)");
            callback(true)
        }
    })
    task.resume()
}

第二个功能envoiPhoto:

    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似乎没有按预期运行。

0 个答案:

没有答案