variable stored property lazy computed swift var lazy-initialization let

stored - lazy var swift



Lazy Var vs Let (3)

Quiero utilizar la inicialización Lazy para algunas de mis propiedades en Swift. Mi código actual se ve así:

lazy var fontSize : CGFloat = { if (someCase) { return CGFloat(30) } else { return CGFloat(17) } }()

El hecho es que una vez que se establece fontSize, NUNCA cambiará. Así que quería hacer algo como esto:

lazy let fontSize : CGFloat = { if (someCase) { return CGFloat(30) } else { return CGFloat(17) } }()

Lo cual es imposible

Solo esto funciona:

let fontSize : CGFloat = { if (someCase) { return CGFloat(30) } else { return CGFloat(17) } }()

Por lo tanto, quiero una propiedad que se cargará de forma diferida pero que nunca cambiará. ¿Cuál es la forma correcta de hacer eso? ¿usar let y olvidarte del init perezoso? ¿O debería usar lazy var y olvidarme de la naturaleza constante de la propiedad?


Como dasblinkenlight señala que las propiedades perezosas siempre se deben declarar como variables en Swift. Sin embargo, es posible hacer que la propiedad sea de solo lectura, por lo que solo se puede mutar desde el archivo de origen en el que se definió la Entidad. Esto es lo más cercano que puedo llegar a definir un "let lazy".

private(set) lazy var fontSize: CGFloat = { if someCase { return 30 } else { return 17 } }()


Esta es la última escritura de las notas de la versión Xcode 6.3 Beta / Swift 1.2 :

deja que las constantes se generalicen para no requerir una inicialización inmediata. La nueva regla es que una constante de let debe inicializarse antes de su uso (como una var), y que solo se puede inicializar: no reasignada o mutada después de la inicialización.

Esto permite patrones como:

let x: SomeThing if condition { x = foo() } else { x = bar() } use(x)

que anteriormente requería el uso de una var, a pesar de que no hay mutación teniendo lugar. (16181314)

Evidentemente, usted no era la única persona frustrada por esto.


Swift book tiene la siguiente nota :

Siempre debe declarar una propiedad diferida como variable (con la palabra clave var), ya que es posible que su valor inicial no se recupere hasta que se complete la inicialización de la instancia. Las propiedades constantes siempre deben tener un valor antes de que se complete la inicialización, y por lo tanto no pueden declararse como flojas.

Esto tiene sentido en el contexto de la implementación del lenguaje, porque todas las propiedades almacenadas constantes se computan antes de que la inicialización de un objeto haya finalizado. No significa que la semántica de let podría haber cambiado cuando se usa junto con lazy , pero no se ha hecho, por lo que var sigue siendo la única opción con lazy en este punto.

En cuanto a las dos opciones que presentó, yo decidiría entre ellas en función de la eficiencia:

  • Si acceder al valor de una propiedad se hace raramente, y es costoso calcularlo por adelantado, usaría var lazy
  • Si se accede al valor en más de 20 ... 30% de los casos o es relativamente barato de calcular, usaría let

Nota: optimizaría aún más su código para insertar el condicional en el inicializador CGFloat :

let fontSize : CGFloat = CGFloat(someCase ? 30 : 17)