在 Swift 中的所有事件完成后,DispatchGroup 通知方法应该只 运行 一次

DispatchGroup notify method should only run once after all events are finished in Swift

我有下面使用“DispatchGroup”的代码:

// class variables
let myUploadGroup = DispatchGroup()
var concatenatedUploadGroupMessage:String = ""

// inside a method I have the code below
for resFoto in resFotosResenhaEscolhidas {
        
        myUploadGroup.enter()
        
        jsonRequestUploadImagem = ResFotosModel.createJsonFotoResenha(resFoto, resenhaDados.IdGedave)
                    
        let requestUploadImagem: NSMutableURLRequest = serviceRepository.clientURLRequest(wsUploadImagem, typeAutho: .basic, parms: "", body: jsonRequestUploadImagem as Dictionary<String, AnyObject>)
        
        serviceRepository.post(requestUploadImagem, retryLogin: true, completion: {isOk,msgError,httpCode,needLogin,response in
            self.checkResponseUploadImagemFotoResenha(response as AnyObject, httpCode)
        })
        
    }

func checkResponseUploadImagemFotoResenha(_ response:AnyObject, _ httpCode:Int) {
    
    if httpCode != 200 {
        let string = String(data: response as! Data, encoding: .utf8)
        print( string!+" \n Erro HTTP: "+String(httpCode) )
        myUploadGroup.leave()
        AlertActions.showBasicAlert(erroParaExibir: string!+" \n Erro HTTP: "+String(httpCode), currentView: self)
    } else {
        // httpCode == 200
        let data: Data = response as! Data // received from a network request, for example
        
        let jsonResponse = try? JSONSerialization.jsonObject(with: data, options: [])
        
        guard let dictionary = jsonResponse as? [String: Any] else { return }
        guard let nestedDictionary = dictionary["RetornoGravacaoImagemWSVO"] as? [String: Any] else { return }
        
        let mensagem = nestedDictionary["mensagem"] as! String
        let codigo = nestedDictionary["codigo"] as! Int
        
        
        if codigo != 200 {
            print("Erro upload foto - codigo: \(codigo)")
            concatenatedUploadGroupMessage = concatenatedUploadGroupMessage+" \(mensagem) - \(codigo) \n"
        } else {
            let nomeArquivo = nestedDictionary["nomeArquivo"] as! String
            concatenatedUploadGroupMessage = concatenatedUploadGroupMessage+" \(nomeArquivo) - \(mensagem) \n"
        }
        
        
        myUploadGroup.leave()
    }
    
    myUploadGroup.notify(queue: DispatchQueue.main) {
        AlertActions.showBasicAlert(erroParaExibir: self.concatenatedUploadGroupMessage, currentView: self)
        print("Finished all requests.")
        CustomLoadingBar.hide(self) // use in conjunction with the Grand Dispatcher Group
    }
    
    
}

我使用“myUploadGroup.enter()”和“myUploadGroup.leave()”发送信号来开始和结束请求。

之后我有了方法“myUploadGroup.notify”。

当所有请求都发出后,例如,开始了 4 个 http 请求,当它们完成时,我可以看到消息“完成所有请求”。在控制台打印4次。

我想做的是当 4 个 http 请求完成后,我只想看到消息消息“完成所有请求”。在控制台上打印一次,而不是看到消息打印 4 次。

我该怎么做?

您正在函数 checkResponseUploadImagemFotoResenha() 中调用 myUploadGroup.notify(),这是从完成处理程序调用的。这意味着您不止一次调用 myUploadGroup.notify()。不要那样做。

像这样重写将请求排队的代码:

for requestInfo in requests {
    myUploadGroup.enter()
    submitRequest( completion: {
       // Process response
       myUploadGroup.leave()
}

myUploadGroup.notify(queue: DispatchQueue.main) {
   // Code to execute once when all the requests have completed
}

请注意我是如何在提交请求的循环之后调用通知的。

我能够找到解决我的问题的方法,而无需重写我的代码来排队我的请求。

我创建了一个 class 变量

var counter:Int = 0

在我的“myUploadGroup.enter()”函数之前添加以下代码

counter = counter + 1

在我的“myUploadGroup.notify”函数中,我添加了这段代码

self.counter = self.counter - 1
if self.counter == 0 {
   print("I run once")
}

现在对我有用了。