Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

288
Vistas
¿Cómo se vuelve a llamar a didSet cuando se establece dentro a través de una función?

Por lo que sé y como se menciona en este hilo, si configuro un valor de propiedad en su observador didSet , no debería volver a activar el observador. Bien, entonces escribí un código como este:

 class B { var i = 0 { didSet { print("didSet called") self.i += 1 } } } var y = B() yi = 2 print(yi)

Este código imprime "didSet called" y 3 como salida como se esperaba. Pero hice un pequeño cambio en este código de la siguiente manera:

 class B { var i = 0 { didSet { print("didSet called") doit(val: self) } } func doit(val: B) { val.i += 1 } } var y = B() yi = 2 print(yi)

Pero ahora cae en un bucle infinito que imprime "didSet called" . ¿Por qué si establezco un valor para la variable dentro didSet pasándolo a través de un argumento de función, didSet nuevamente? Dado que el objeto pasado debe referirse al mismo objeto, no sé por qué sucede esto. Probé y si lo configuro a través de un cierre en didSet en lugar de una función normal, vuelve a un bucle infinito.

Actualización: es divertido que incluso esto desencadene un bucle infinito:

 class B { var i = 0 { didSet { print("called") doit() } } func doit() { self.i += 1 } }
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Después de consultar con Swift github y hacer preguntas sobre este problema, descubrí que este problema es más complejo de lo que parece. Pero hay una regla específica sobre este problema:

El observador didSet no se activará solo si el acceso a la propiedad dentro de su propio observador didSet se puede realizar a través del acceso directo a la memoria.

El problema es que es un poco ambiguo cuándo el acceso a la propiedad será directo (a menos que probablemente sea un desarrollador de Swift). Una característica importante que tiene un efecto en mi pregunta es esta:

El método de instancia de clase nunca accede directamente a las propiedades de clase.

Esta cita muestra un problema con mi código, aunque puedo argumentar que cuando un miembro de la instancia debería poder acceder a la propiedad directamente siempre que lo llame en didSet observe. Cuando tengo un código como este:

 class B { var i = 0 { didSet { print("called") doit() } } func doit() { self.i += 1 } }

La función doit() no puede acceder a i directamente, lo que activa didSet nuevamente y causa un bucle infinito.

Ahora, ¿cuál es la solución?

Puede usar inout para pasar propiedades de su propio didSet a una función de instancia sin activar didSet . Algo como esto:

 class B { var i = 0 { didSet { print("called") doit(&i) } } func doit(_ i: inout Int) { i += 1 } }

Y una última cosa. A partir de Swift 5 , las condiciones para seleccionar el acceso directo a la memoria para las propiedades dentro de su propio didSet serán más restringidas. Según github, las únicas condiciones que utilizarán el acceso directo a la memoria son las siguientes:

 Within a variable's own didSet/willSet specifier, access its storage directly if either: 1) It's a 'plain variable' (ie a variable that's not a member). 2) It's an access to the member on the implicit 'self' declaration. If it's a member access on some other base, we want to call the setter as we might be accessing the member on a *different* instance.

Esto significa que los códigos como los siguientes activarán un bucle infinito mientras que ahora no lo hace:

 class B { var i = 0 { didSet { print("called") var s = self si += 1 } } }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda