UnsafePointer y UnsafeMutablePointer
Lea y escriba en la memoria sin procesar con cuidado.
UnsafePointer y UnsafeMutablePointer es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 2 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.
Punteros tipados en Swift
Las referencias seguras de Swift nunca exponen direcciones sin procesar, pero al interoperar con C o crear estructuras de datos de bajo nivel puede recurrir a punteros tipados: UnsafePointer<T> para acceso de solo lectura y UnsafeMutablePointer<T> para lectura y escritura.
Un puntero tipado conoce el tipo del elemento, por lo que puede calcular las distancias y leer un valor con el tipo adecuado.
// A pointer to an Int we can read but not write
func readFirst(_ p: UnsafePointer<Int>) -> Int {
return p.pointee
}La propiedad pointee
pointee es el valor al que apunta actualmente el puntero. En un puntero mutable, puede leerlo y asignarle un valor; en un puntero de solo lectura, solo puede leerlo.
Acceder a pointee en memoria no inicializada o ya liberada provoca un comportamiento indefinido; el sistema de tipos no lo detectará.
let p = UnsafeMutablePointer<Int>.allocate(capacity: 1)
p.initialize(to: 42)
print(p.pointee) // 42
p.pointee = 99
print(p.pointee) // 99Asignar memoria
UnsafeMutablePointer<T>.allocate(capacity:) reserva espacio para capacity elementos, pero no los inicializa. La memoria está sin procesar y leerla antes de inicializarla es ilegal.
// Reserve space for 3 Doubles (uninitialized)
let buffer = UnsafeMutablePointer<Double>.allocate(capacity: 3)
// Must initialize before reading any elementInicializar y desinicializar
Antes de leer, debe usar initialize. Antes de desasignar tipos que necesitan limpieza, como las clases o las cadenas, debe usar deinitialize para liberar sus recursos.
El ciclo de vida es: allocate → initialize → use → deinitialize → deallocate.
let p = UnsafeMutablePointer<String>.allocate(capacity: 1)
p.initialize(to: "hello")
print(p.pointee)
p.deinitialize(count: 1) // releases the String
p.deallocate()Combine siempre allocate con deallocate
Cada allocate debe corresponderse exactamente con un deallocate; de lo contrario, se produce una fuga de memoria. Usar defer justo después de la asignación es el patrón más seguro, porque se ejecuta independientemente de cómo termine la función.
func process() {
let p = UnsafeMutablePointer<Int>.allocate(capacity: 1)
defer { p.deallocate() }
p.initialize(to: 7)
print(p.pointee)
} // deallocate runs here automaticallyAritmética de punteros
Los punteros tipados admiten indexación y aritmética en unidades de elementos, no en bytes. p + 2 avanza dos distancias de T. p[i] es una forma abreviada de (p + i).pointee.
let p = UnsafeMutablePointer<Int>.allocate(capacity: 3)
p.initialize(repeating: 0, count: 3)
p[0] = 10
p[1] = 20
p[2] = 30
print((p + 1).pointee) // 20
p.deinitialize(count: 3)
p.deallocate()Inicializar varios elementos
Para un bloque de memoria, initialize(repeating:count:) establece el mismo valor en cada posición, mientras que initialize(from:count:) copia los valores desde otro buffer. Ambos inicializan por completo el rango, por lo que es seguro leerlo.
let dst = UnsafeMutablePointer<Int>.allocate(capacity: 4)
dst.initialize(repeating: 5, count: 4)
print(dst[3]) // 5
dst.deinitialize(count: 4)
dst.deallocate()Solo lectura frente a mutable
Una función que solo inspecciona datos debe recibir un UnsafePointer<T>; una que los modifica debe recibir un UnsafeMutablePointer<T>. Un puntero mutable se convierte implícitamente en uno de solo lectura, pero no al revés; esto impone la intención en el límite de la API.
func sum(_ p: UnsafePointer<Int>, _ n: Int) -> Int {
var total = 0
for i in 0..<n { total += p[i] }
return total
}
// A mutable pointer can be passed here directlywithUnsafePointer para variables locales
Para obtener un puntero temporal a un valor existente sin asignar memoria, use withUnsafePointer(to:) o su forma mutable. El puntero solo es válido dentro del closure; no permita que escape.
var value = 100
withUnsafeMutablePointer(to: &value) { ptr in
ptr.pointee += 1
}
print(value) // 101Errores habituales
Los punteros tipados son potentes, pero no admiten errores:
- Leer
pointeeantes deinitializeprovoca un comportamiento indefinido. - Olvidar
deinitializeen tipos que contienen recursos provoca fugas. - Permitir que escape un puntero de
withUnsafePointerproduce un puntero colgante.
El compilador confía en usted; aquí no hay protecciones en tiempo de ejecución.
// DANGEROUS — pointer escapes the closure
// var escaped: UnsafePointer<Int>?
// withUnsafePointer(to: &x) { escaped = $0 }
// escaped!.pointee // dangling, undefined behaviorUna pequeña pila manual
Al juntarlo todo: asigne un bloque, trátelo como una colección de elementos mediante la indexación y, después, límpielo. Esta es la base de las colecciones personalizadas y de la interoperabilidad con C.
let n = 3
let stack = UnsafeMutablePointer<Int>.allocate(capacity: n)
stack.initialize(repeating: 0, count: n)
for i in 0..<n { stack[i] = i * i }
// stack now holds 0, 1, 4
stack.deinitialize(count: n)
stack.deallocate()Comprobación rápida
Recuerde el ciclo de vida correcto de un puntero.
Resumen
Ahora conoce los punteros tipados:
UnsafePointerpermite leer;UnsafeMutablePointerpermite leer y escribir.pointeepermite acceder al valor; la aritmética se realiza en unidades de elementos.- El ciclo de vida es allocate → initialize → use → deinitialize → deallocate, idealmente protegido con
defer.
A continuación verá cómo los punteros de buffer encapsulan una región contigua completa en una API compatible con Collection.
Preguntas frecuentes
¿La lección «UnsafePointer y UnsafeMutablePointer» es gratis?
Sí — el texto completo de «UnsafePointer y UnsafeMutablePointer» 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 «UnsafePointer y UnsafeMutablePointer»?
Lea y escriba en la memoria sin procesar con cuidado. 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 2 de 4.
¿Cuánto tiempo toma la lección «UnsafePointer y UnsafeMutablePointer»?
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
- MemoryLayout y alineación
- UnsafePointer y UnsafeMutablePointer
- Punteros de búfer inseguros
- withUnsafeBytes e interoperabilidad con C