Swift 3: el uso de cierre de parameters que no escapan puede permitirle escaping

Tengo la siguiente function donde tengo el manejador de finalización pero obtengo este error:

Closure use of non-escaping parameter may allow it to escape 

Aquí está mi código:

 func makeRequestcompletion(completion:(_ response:Data, _ error:NSError)->Void) { let urlString = URL(string: "http://someUrl.com") if let url = urlString { let task = URLSession.shanetworking.dataTask(with: url, completionHandler: { (data, urlRequestResponse, error) in completion(data, error) // <-- here is I'm getting the error }) task.resume() } } 

introduzca la descripción de la imagen aquí ¿Alguno de ustedes sabe por qué recibo este error?

Apreciaré mucho tu ayuda.

Parece que necesita definir explícitamente que se permite el escape.

De los documentos de Apple Developer ,

Se dice que un cierre se libera de una function cuando el cierre se pasa como un argumento a la function, pero se invoca después de que la function regrese. Cuando declara una function que toma un cierre como uno de sus parameters, puede escribir @escaping antes del tipo de parámetro para indicar que se permite el escape.

TLDR; Agregue la palabra key @escaping después de la variable de finalización:

 func makeRequestcompletion(completion: @escaping (_ response:Data, _ error:NSError)->Void) { let urlString = URL(string: "http://someUrl.com") if let url = urlString { let task = URLSession.shanetworking.dataTask(with: url, completionHandler: { (data, urlRequestResponse, error) in completion(data, error) // <-- here is I'm getting the error }) task.resume() } } 

Un cierre de "escape" es un cierre que puede sobrevivir al scope en el que se creó. Los cierres de escape requieren un cuidado especial en cuanto al recuento de references y la gestión de la memory y pueden ser más difíciles de optimizar.

Antes de Swift 3, el valor pnetworkingeterminado para los cierres era suponer que se estaban escapando. Esto significaba que los desarrolladores tenían que identificar específicamente los cierres que se sabe que no escapan para permitir que el comstackdor realice optimizaciones. La comunidad descubrió que, de hecho, el comstackdor podría descubrir por sí mismo si un cierre se está escapando o no, y decidió que un enfoque agresivo para escaping podría dar como resultado un código más rápido. El resultado es que ahora se supone que los cierres no escapan y que se deben marcar los cierres que escapan con el atributo @escaping .

En su caso, el cierre que URLSession.shanetworking.dataTask acepta es en sí mismo un cierre de escape, por lo que si usa un cierre dentro de él, también debe marcar @escaping .

@escaping es infeccioso para todos los methods de llamada, y el comstackdor determina cuándo debe includelo.

Considere este ejemplo (que comstack):

 dispatchSometime( { print("Oh yeah") }) func dispatchSometime(_ block: ()->()) { dispatchNow(block) } func dispatchNow(_ block: ()->()) { block() } 

Sin embargo, este ejemplo modificado produce dos errores de tipo que el non-escaping parameter may allow it to escape :

 dispatchSometime( { print("Oh yeah") }) func dispatchSometime(_ block: ()->()) { dispatchLater(block) } func dispatchLater(_ block: ()->()) { DispatchQueue.main.async(execute: block) } 

El envío en principal significa que el método dispatchLater necesita @escaping , y una vez que haya agregado eso, el método dispatchSometime también requiere @escaping para que el ejemplo se compile.

 dispatchSometime( { print("Oh yeah") }) func dispatchSometime(_ block: @escaping ()->()) { dispatchLater(block) } func dispatchLater(_ block: @escaping ()->()) { DispatchQueue.main.async(execute: block) } 

Sin embargo, la comida es simplemente:

  • Sigue agregando @escaping a la cadena de llamadas hasta que el comstackdor deje de quejarse.
  • La palabra key no cambia nada: es una advertencia que dice, esencialmente, "tenga cuidado de usar weak con las variables capturadas, ya que pueden conservarse junto con el bloque en sí".

Trascendencia

El caso realmente divertido con esto es donde tienes que ajustar varios methods para include la palabra key @escaping , lo que hace que el comstackdor deje de quejarse. Sin embargo, si esos methods realmente se ajustan a un protocolo, los methods de ese protocolo también deben get la palabra key @escaping , que también infecta a todos los demás conformantes del protocolo. ¡Divertido!