отправка нескольких запросов DataSask для URLSession и ожидание завершения - PullRequest
0 голосов
/ 05 сентября 2018

Мне нужно отправить несколько запросов 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()
}

второй функционал фото:

    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 для отправки изображений будут завершены, мне нужно будет отключить индикатор выполнения и отобразить еще одно предупреждение, детализирующее операцию.

На сегодняшний день операции не синхронизируются, и код пытается отключить индикатор выполнения, даже если операции не завершены. Запуск загрузки фотографий начинается после первого 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 не работает, как я ожидаю.

...