diferir en la function no funcionó en Swift 2.0

Estoy probando Swift 2.0 y el nuevo defer palabra key en un parque infantil:

 func branch() -> String { var str = "" defer { str += "xxx" } str += "1" let counter = 3; if counter > 0 { str += "2" defer { str += "yyy" } str += "3" } str += "4" return str } let bran = branch() 

Esperaba que el bran sea "123yyy4xxx" , pero en realidad es "123yyy4"

¿Por qué mi defer (str += "xxx") no funciona como se esperaba?

Una sentencia deferente difiere de la ejecución hasta que se abandona el scope actual.

Que dice la manzana. Entonces, la statement diferida se ejecutará después de la statement de devolución. Es por eso que no puede ver el resultado esperado.

Greg es correcto y si quieres get el mismo resultado con tu código, puedes hacerlo de esta manera:

 var str = "" func branch() { str = "" defer { str += "xxx" } str += "1" let counter = 3 if counter > 0 { str += "2" defer { str += "yyy" } str += "3" } str += "4" } branch() str //"123yyy4xxx" 

En primer lugar: el defer se ejecuta como se puede ver claramente cuando se agrega una print(str) .

Ahora para explicar por qué el valor devuelto no refleja el valor cambiado:
La razón de esto es que String es inmutable: cada vez que escribe str += something crea una instancia String totalmente nueva y la almacena dentro de str .

Si escribe return str que devuelve la instancia actual de str que es 123yyy4 . Luego se invoca el 123yyy4xxx y asigna la String 123yyy4xxx completamente nueva y no 123yyy4xxx a str . Pero eso no cambia el object de String anterior almacenado dentro de str , simplemente lo sobrescribe y, por lo tanto, no afecta el return que ya "sucedió".

Si cambia su método para usar NSMutableString en su lugar, siempre operará en la misma instancia y el resultado, por lo tanto, mostrará correctamente 123yyy4xxx :

 func branch() -> NSMutableString { var str = NSMutableString() defer { str.appendString("xxx") } str.appendString("1") let counter = 3; if counter > 0 { str.appendString("2") defer { str.appendString("yyy") } str.appendString("3") } str.appendString("4") return str } let bran1 = branch() 

En ese código, la devolución devuelve la instancia almacenada en str y el aplazamiento altera esa instancia , no asigna una nueva instancia pero cambia la ya existente.

Por razones de explicación, puede intentar ver la dirección de memory de str en diferentes etapas:

  • en el momento de la return
  • antes de cambiar str en el bloque de defer
  • después de cambiarlo

Para NSMutableString los tres casos producirán la misma dirección de memory, lo que significa que la instancia permanece igual. Sin embargo, String imprime dos direcciones de memory diferentes, lo que provoca que la String devuelta apunte a someAddress y la diferida para apuntar a someOtherAddress .