xcode - and - Actualización de cierres a Swift 3-@escaping
swift @escaping and completion handler (2)
He actualizado mi código a Xcode 8.0 beta 6, pero me quedé atrapado con lo que parece ser sobre el nuevo cierre predeterminado sin escape.
En el siguiente código, Xcode sugiere agregar
@escaping
de la
completion:
en la primera línea del código a continuación, pero eso aún no se compila y va en círculos.
* *
(
EDITAR
: de hecho, @escaping debe agregarse
después de la
completion:
como sugiere Xcode. La alerta aún puede mostrarse, pero la limpieza y la compilación lo eliminarán). * ¿Cómo debe reescribirse / repararse este código para que funcione en la versión actualizada? Swift 3?
He echado un vistazo al nuevo manual, pero no pude encontrar ejemplos de código adecuados.
func doSomething(withParameter parameter: Int, completion: () -> ()) {
// Does something
callSomeOtherFunc(withCompletion: completion)
}
// Calling the method and execute closure
doSomething(withParameter: 2) {
// do things in closure
}
Cualquier ayuda muy apreciada!
@noescape
Desde xcode 8 beta 6
@noescape
es el valor predeterminado.
Antes de eso,
@escaping
era el valor predeterminado.
Cualquiera que actualice a Swift 3.0 desde versiones anteriores podría enfrentar este error.
No puede almacenar un cierre
@noescape
dentro de una variable.
Porque si puede almacenar un cierre dentro de una variable, puede ejecutar el cierre desde cualquier parte de su código.
Pero
@noescape
afirma que el parámetro de cierre no puede escapar del cuerpo de la función.
Esto dará un error del compilador en Xcode 8
class MyClass {
var myClosure: (() -> ())?
func doSomething(finishBlock: () -> ()) {
myClosure = finishBlock // ‼️ Error: Assigning non-escaping parameter ''finishBlock'' to an @escaping closure
}
}
Esto compilará bien (explícitamente escriba
@escaping
)
class MyClass {
var myClosure: (() -> ())?
func doSomething(finishBlock: @escaping () -> ()) {
myClosure = finishBlock
}
}
Beneficios de
@noescape
:
- El compilador puede optimizar su código para un mejor rendimiento
- El compilador puede encargarse de la gestión de la memoria.
- No hay necesidad de usar una referencia débil de uno mismo en el cierre
Para obtener más información, consulte:
Establecer cierres sin escape como predeterminados
Swift 3: los atributos del parámetro de cierre ahora se aplican al tipo de parámetro, y no al parámetro en sí
Antes de Swift 3, los atributos de cierre
@autoclosure
y
@noescape
solían ser atributos para el
parámetro de
cierre, pero ahora son atributos para el
tipo de
parámetro;
ver la siguiente propuesta de evolución Swift aceptada:
Su pregunta específica se refiere al atributo de tipo de parámetro
@escaping
(para el cual se aplica la misma nueva regla), como se describe en la propuesta de evolución Swift aceptada para permitir que los parámetros de cierre no escapen de forma predeterminada:
Estas propuestas ahora se implementan en la etapa beta de Xcode 8 (consulte las notas de la versión de Xcode 8 beta 6 ; se necesita iniciar sesión en la cuenta de desarrollador para acceder)
Nuevo en Xcode 8 beta 6 - Compilador Swift: lenguaje Swift
Los parámetros de cierre no escapan de forma predeterminada, en lugar de anotarse explícitamente con
@noescape
. Use@escaping
para indicar que un parámetro de cierre puede escapar.@autoclosure(escaping)
ahora se escribe como@autoclosure @escaping
. Las anotaciones@noescape
y@autoclosure(escaping)
están en desuso. (SE-0103)...
Nuevo en Xcode 8 beta - Compiladores Swift y Apple LLVM: lenguaje Swift
Los
@noescape
y@autoclosure
ahora deben escribirse antes del tipo de parámetro en lugar de antes del nombre del parámetro. [SE-0049]
Por lo tanto, utiliza el atributo
@escaping
no predeterminado de la siguiente manera;
aplicado al
tipo
del parámetro de cierre, en lugar del parámetro en sí
func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
// ...
}
(Incluyendo mi respuesta a una pregunta en un comentario votado a continuación, ya que los comentarios no son datos persistentes sobre SO)
@Cristi Băluță: "¿Qué hace el escape? Nunca he visto estas palabras clave antes de la conversión automática swift3 ..."
Consulte, por ejemplo, el enlace a la
propuesta de evolución SE-0103 anterior
(así como el texto citado de las notas de la versión beta 6): anteriormente, los parámetros de cierre escapaban por defecto (por lo tanto, no es necesario que exista una anotación explícita para escapar), pero ahora, en cambio, no escapan, por defecto.
De ahí la adición de
@escaping
para anotar explícitamente que un parámetro de cierre puede escapar (contrario a su comportamiento predeterminado).
Esto también explica por qué
@noescape
ahora está en desuso (no es necesario anotar el comportamiento predeterminado).
Para explicar lo que significa que se está escapando un parámetro de cierre, cito la Referencia del lenguaje: atributos :
"Aplique este atributo al tipo de un parámetro en una declaración de método o función para indicar que el valor del parámetro se puede almacenar para una ejecución posterior. Esto significa que el valor puede sobrevivir a la duración de la llamada".