willset y el didset
🧐
react, is that you?
Domina cómo reaccionar a cambios en tus propiedades en Swift con property observers. Verás cuándo usar willSet y didSet, cómo se diferencian de una stored property y por qué recuerdan a las computed properties. Un ejemplo práctico con un podómetro ilustra el flujo completo, y un reto final consolida el aprendizaje.
¿Qué son los property observers y cuándo usarlos?
Los property observers se añaden a una propiedad para ejecutar lógica antes y después de cambiar su valor. Son ideales cuando necesitas validar rangos, lanzar notificaciones o imprimir mensajes al modificar datos. Ejemplo clásico: una propiedad de vida en un videojuego que no debe bajar de cero para evitar game over.
En propiedades de una estructura o una clase, puedes definir dos observadores: willSet (futuro) y didSet (pasado). Permiten “escuchar” cambios sin convertir la propiedad en una computed property.
¿Cómo se diferencian willSet y didSet?
newTotalSteps.En síntesis: antes de asignar, willSet; después de asignar, didSet.
¿Cómo se relacionan con computed properties?
Comparten la idea de “reaccionar” al acceso o cambio, pero aquí la propiedad es almacenada (stored property). Es decir, guardas el valor y, además, observas sus cambios con willSet/didSet.
¿Cómo implementar un StepCounter con observers en Swift?
Un podómetro necesita contar pasos y avisar de incrementos. Con una clase StepCounter y una stored property totalSteps, willSet imprime el nuevo total y didSet calcula el incremento usando oldValue.
class StepCounter { var totalSteps: Int = 0 { willSet(newTotalSteps) { print("El número de pasos va a subir hasta \(newTotalSteps)") } didSet { if totalSteps > oldValue { print("El número de pasos ha incrementado en \(totalSteps - oldValue)") } } } } let stepCounter = StepCounter() stepCounter.totalSteps = 200 // mensajes: "va a subir hasta 200"; "ha incrementado en 200". stepCounter.totalSteps = 520 // mensajes: "va a subir hasta 520"; "diferencia 320". stepCounter.totalSteps += 1234 // total 1754; incremento de 1234.
Claves del ejemplo:
totalSteps inicia en 0.¿Qué práctica refuerza el control de rangos con observers?
Pon en práctica el patrón de validación con un atributo de vida del jugador. Objetivo: mantenerla dentro de 0 a 100 y comunicar estados críticos.
Sugerencias para el reto:
vida inicial. Controla cambios con willSet o didSet.Habilidades que entrenas:
¿Te animas a extenderlo con contadores de eventos o notificaciones? Comparte tu implementación y dudas en comentarios.
Domina cómo reaccionar a cambios en tus propiedades en Swift con property observers. Verás cuándo usar willSet y didSet, cómo se diferencian de una stored property y por qué recuerdan a las computed properties. Un ejemplo práctico con un podómetro ilustra el flujo completo, y un reto final consolida el aprendizaje.
Los property observers se añaden a una propiedad para ejecutar lógica antes y después de cambiar su valor. Son ideales cuando necesitas validar rangos, lanzar notificaciones o imprimir mensajes al modificar datos. Ejemplo clásico: una propiedad de vida en un videojuego que no debe bajar de cero para evitar game over.
En propiedades de una estructura o una clase, puedes definir dos observadores: willSet (futuro) y didSet (pasado). Permiten “escuchar” cambios sin convertir la propiedad en una computed property.
newTotalSteps.En síntesis: antes de asignar, willSet; después de asignar, didSet.
Comparten la idea de “reaccionar” al acceso o cambio, pero aquí la propiedad es almacenada (stored property). Es decir, guardas el valor y, además, observas sus cambios con willSet/didSet.
Un podómetro necesita contar pasos y avisar de incrementos. Con una clase StepCounter y una stored property totalSteps, willSet imprime el nuevo total y didSet calcula el incremento usando oldValue.
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("El número de pasos va a subir hasta \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("El número de pasos ha incrementado en \(totalSteps - oldValue)")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200 // mensajes: "va a subir hasta 200"; "ha incrementado en 200".
stepCounter.totalSteps = 520 // mensajes: "va a subir hasta 520"; "diferencia 320".
stepCounter.totalSteps += 1234 // total 1754; incremento de 1234.
Claves del ejemplo:
totalSteps inicia en 0.Pon en práctica el patrón de validación con un atributo de vida del jugador. Objetivo: mantenerla dentro de 0 a 100 y comunicar estados críticos.
Sugerencias para el reto:
vida inicial. Controla cambios con willSet o didSet.Habilidades que entrenas:
¿Te animas a extenderlo con contadores de eventos o notificaciones? Comparte tu implementación y dudas en comentarios.
willset y el didset
🧐
react, is that you?
Se parece un poco al didMount de react JAJAAJJAJA

willSet is called just before the value is stored. didSet is called immediately after the new value is stored.
Cree un pequeño combate con la vida fija en 50 pero daño variable. Hay dos conjuntos de willSet/didSet para generar mensajes dependiendo de quien gana y quien pierde. Estuve un rato rompiendo código hasta que me salió 😅
func randomNumber(_ min: Int, _ max: Int) -> Int {
return Int.random(in: min...max)
}
class PlayersLife{
var totalHpAlly = 50{
willSet(newHp){
print("Now you have \(newHp) HP points")
}
didSet{
if totalHpAlly < oldValue && totalHpAlly > 0{
print("Your HP points are reduced in \(oldValue - totalHpAlly)")
} else {
print("Your HP points are reduced in \(oldValue - totalHpAlly) ... GAME OVER")
}
}
}
var totalHpEnemy = 50{
willSet(newEnemyHp){
print("Now you enemy have \(newEnemyHp) HP points")
}
didSet{
if totalHpEnemy <= oldValue && totalHpEnemy > 0{
print("Your enemy HP points are reduced in \(oldValue - totalHpEnemy) HP points")
} else {
print("Your enemy HP points are reduced in \(oldValue - totalHpEnemy)... YOU WIN")
}
}
}
}
let enemyAttack = randomNumber(1, 10)
let allyDefense = randomNumber(1, 10)
let damage = randomNumber(10, 50)
print("numbers: \(enemyAttack)|\(allyDefense)|\(damage)") // ver los randomNumber
let playerGame = PlayersLife()
let enemyGame = PlayersLife()
if enemyAttack > allyDefense {
playerGame.totalHpAlly -= damage
} else if enemyAttack < allyDefense {
enemyGame.totalHpEnemy -= damage
} else {
print("Nice fight!.. We have a tie!")
}
Creo que nadie aprovecho el curso de Swift jajajaja
Tuve algunas dificultades para comprenderlo pero lo realice de esta manera
Se debe tener en cuenta el willSet que solo es para observar información no realiza cambios y en el otro caso expuse que el valor puede llegar a ser mayor o menor a la vida entre 0 a 100 entonces, se reinicia el valor y pues cada condición para la vida
// HOMEWORK - EXAMPLE
class Player {
var life: Int = 100 {
willSet(newValue) { // solo observación
print("La vida actual es: \(newValue)")
}
didSet {
if life > 100 {
life = 100
}
if life < 0 {
life = 0
print("Game Over")
return
}
switch life {
case 0...20:
print("Estado critico")
case 21...50:
print("Vida baja")
case 51...99:
print("Vida normal")
default:
print("Vida maxima")
}
}
}
}
let player = Player()
player.life = 10

class liveCharacter {
var totalLive: Int = 0 {
willSet(newLive){
if(totalLive<=0){
print("gameOver")
}
}didSet{
if(totalLive>100){
totalLive = 100
}
}
}
}
class lifeGame {
var lifePoints: Int = 100 {
willSet(newLifePoints) {
print("\(newLifePoints) A tus puntos de vida")
}
didSet {
if lifePoints > 100{
print( "Has superado los 100 puntos de vida, Tus puntos de vida serán 100")
lifePoints = 100
}
if(lifePoints <= 0){
lifePoints = 0
print("Se han agotado tus puntos de vida")
print("GAME OVER")
}else{
print("Puntos de vida actuales: \(lifePoints)")
}
}
}
}
let lifeGamePlayer = lifeGame()
lifeGamePlayer.lifePoints += 50
lifeGamePlayer.lifePoints -= 150
public class charLife {
public var lifePoints = 100 {
willSet(newLifePoints){
print("life points -> ❤️ \(newLifePoints)")
}
didSet {
if lifePoints == 0 {
print("Game Over")
}
if lifePoints < oldValue {
print("life points lost -> 🖤 \(self.lifePoints - oldValue) ")
}
if lifePoints > 100 {
self.lifePoints = 100
print("max life 100 reached")
}
}
}
public init(lifePoints: Int = 100) {
self.lifePoints = lifePoints
}
public func heal(healPoints: Int) -> Int{
self.lifePoints += healPoints
print("you have healed \(healPoints) life points -> 🔋❤️ \(lifePoints)")
return self.lifePoints
}
}
let charlife = charLife()
charlife.lifePoints = 30
charlife.heal(healPoints:20)
charlife.heal(healPoints:20)
charlife.heal(healPoints:20)
charlife.heal(healPoints:20)
charlife.lifePoints = 0