Мне нужно отправить несколько запросов POST на мой сервер, но при этом у меня возникла проблема с синхронизацией.
Мне нужно сделать следующее:
- отображать индикатор выполнения (идет загрузка ...)
- отправьте первый запрос POST
- за каждое 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 не работает, как я ожидаю.