fabiobh
fabiobh

Reputation: 779

How to write a completion handler in a separated block of code in Swift with parameters out of scope

I was trying to make my code clean and decouple the code below, I want to remove the trailing completion handler from it and write the completion handler in another blck of code.

func uploadMarcasMetodoNovo(_ id_resenha: Int) {
    
    let resenhaDados:ResDadoModel = db.readDadosResenhaById(id_resenha)
    let resenhaMarcas:[ResMarcasModel] = db.readResMarca(id_resenha)

    // this for loop runs about for 7 times                
    for marca in resenhaMarcas { 

        contadorUploadMarcas = contadorUploadMarcas + 1
        myUploadGroupMarcas.enter()
        
        jsonRequestUploadImagemGrafica = ResMarcasModel.createJsonMarcaResenha(marca, resenhaDados.IdGedave )
        
        let json: [String: Any] = jsonRequestUploadImagemGrafica
        guard let jsonData = try? JSONSerialization.data(withJSONObject: json) else {
            print("guard jsonData error")
            return
        }
        
        let requestImagemGrafica = requestUploadFotos(jsonData)
        let task = URLSession.shared.dataTask(with: requestImagemGrafica) { data, response, error in
            if let error = error {
                print("error: \(String(describing: error))")
                return
            }
            
            print("data")
            guard let returnData = String(data: data!, encoding: .utf8) else {
                print("returnData guard fail")
                return
            }
            print("returnData")
            print(returnData)
            
            self.confirmStatusEnviada(marca)
            self.myUploadGroupMarcas.leave()
            print("end TASK")
        }
        task.resume()
    }
    
    myUploadGroupMarcas.notify(queue: DispatchQueue.main) {
        print("myUploadGroupMarcas notify")
        // more code ...
    }
}

This is the part that I write creating a separated completion handler

let myCompletionHandler: (Data?, URLResponse?, Error?) -> Void = {
  (data, response, error) in
    if let error = error {
        print("error: \(String(describing: error))")
        return
    }
    
    print("data")
    guard let returnData = String(data: data!, encoding: .utf8) else {
        print("returnData guard fail")
        return
    }
    self.confirmStatusEnviada(marca)                
    self.myUploadGroupMarcas.leave()
    
}

but it won't work because in the last two lines of code are used paramters that are out of scope. The parameter "marca" and the parameter "myUploadGroupMarcas" are out of scope. Is there a way to use these parameters inside the separated completion handler function?

Upvotes: 0

Views: 696

Answers (1)

user1922718
user1922718

Reputation: 147

Ok based on our comments above, this is the route I would try: Write a short completion handler that calls your longer completion handler, passing the variables that are out of scope.

let task = URLSession.shared.dataTask(with: requestImagemGrafica) { data, response, error in

myCompletionHandler(data, response, error, marca, myUploadGroupMarcas)

}

Then you add two parameters to your completion handler in the function definition:

let myCompletionHandler: (Data?, URLResponse?, Error?, MarcaClass, myUploadGroupMarcas) -> Void

Obviously you need to replace MarcaClass with the actual class type that is marca and myUploadGroupMarcas seems to be a function so you'd need to write an appropriate parameter type for that.

Upvotes: 1

Related Questions