Listas de captura y weak self
Evite ciclos de retención con [weak self].
Listas de captura y weak self es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Swift Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Swift Academy incluye 4 lecciones en total.
El riesgo de un ciclo de retención
Cuando un objeto almacena una closure escapable que captura self mediante una referencia fuerte, cada uno mantiene al otro vivo indefinidamente — es un ciclo de retención que provoca una fuga de memoria.
Un ciclo de referencias fuertes
La closure captura self mediante una referencia fuerte y self mantiene la closure — ninguno de los dos se libera:
class Owner {
var onEvent: (() -> Void)?
func setup() {
onEvent = { print(self.describe()) } // strong self -> cycle
}
func describe() -> String { "Owner" }
}
let o = Owner(); o.setup()
o.onEvent?() // "Owner" (but leaks)Listas de captura
Una lista de captura al principio de una closure, { [weak self] in ... }, controla cómo se mantiene cada referencia capturada: mediante weak o unowned en lugar de una referencia fuerte.
Romper el ciclo con weak self
[weak self] captura self como un opcional que no lo mantiene vivo:
class Owner {
var onEvent: (() -> Void)?
func setup() {
onEvent = { [weak self] in
print(self?.describe() ?? "gone")
}
}
func describe() -> String { "Owner" }
}
let o = Owner(); o.setup()
o.onEvent?() // "Owner" (no cycle)weak convierte self en opcional
Con [weak self], self se convierte en Self?, por lo que debe desenvolverlo:
class Worker {
var tag = "W"
lazy var job: () -> Void = { [weak self] in
guard let self = self else { return }
print(self.tag)
}
}
let w = Worker()
w.job() // "W"El patrón guard let self
Vuelva a vincular self al principio para que el resto de la closure use una referencia fuerte y no opcional:
class Service {
var name = "S"
lazy var run: () -> Void = { [weak self] in
guard let self else { return }
print(self.name)
print("still \(self.name)")
}
}
Service().run() // "S" / "still S"weak frente a unowned
weak produce un opcional y es seguro si el objeto puede haber desaparecido. unowned no es opcional y es más rápido, pero provoca un fallo si se accede a él después de desasignar el objeto — úselo solo cuando se garantice que self vivirá más que la closure.
Usar unowned
Elija unowned cuando la closure no pueda vivir más que self:
class Timer2 {
var ticks = 0
lazy var tick: () -> Void = { [unowned self] in
self.ticks += 1
}
}
let t = Timer2()
t.tick(); t.tick()
print(t.ticks) // 2Capturar propiedades concretas
Capture solo lo que necesita en lugar de todo self — a veces eso evita por completo el ciclo:
class VM {
let id = 42
lazy var printer: () -> Void = { [id] in print(id) }
}
VM().printer() // 42Las closures no escapables no necesitan weak
Las closures síncronas y no escapables, como map, no provocan ciclos, por lo que capturar self mediante una referencia fuerte es correcto:
class Calc {
let factor = 3
func scale(_ xs: [Int]) -> [Int] {
xs.map { $0 * self.factor } // safe, non-escaping
}
}
print(Calc().scale([1, 2])) // [3, 6]Regla práctica
Use [weak self] para las closures almacenadas o escapables que hagan referencia a self. Recurra a unowned solo cuando se garantice que self seguirá vivo. Omita las listas de captura en las closures no escapables.
class P {
var n = "P"
var stored: (() -> Void)?
func arm() { stored = { [weak self] in print(self?.n ?? "-") } }
}
let p = P(); p.arm(); p.stored?() // "P"Comprobación rápida
¿Por qué se usa [weak self] en una closure escapable almacenada?
Repaso
Ha aprendido sobre las listas de captura:
- Capturar self mediante una referencia fuerte en una closure escapable almacenada crea un ciclo de retención (una fuga)
[weak self]lo rompe; self se convierte en opcional: useguard let selfunownedno es opcional y es más rápido, pero provoca un fallo si self ha desaparecido- Las closures no escapables no necesitan listas de captura
Siguiente: autoclosures.
Preguntas frecuentes
¿La lección «Listas de captura y weak self» es gratis?
Sí — el texto completo de «Listas de captura y weak self» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Swift Academy, actualiza a CoddyKit PRO. El curso de Swift Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Listas de captura y weak self»?
Evite ciclos de retención con [weak self]. Practicas Swift Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Swift Academy?
No se requiere experiencia previa. Swift Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Listas de captura y weak self»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Swift Academy?
Sí. Cada lección de Swift Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Captura de valores por referencia
- Cierres escapables
- Listas de captura y weak self
- Autoclosures