KeyPaths modificables y de referencia
Lea y escriba mediante rutas de claves.
KeyPaths modificables y de referencia 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.
Rutas de claves de solo lectura y modificables
Un KeyPath normal solo puede leer un valor. Para escribir mediante una ruta de claves necesita una variante modificable. Swift tiene dos: una para tipos por valor y otra para tipos por referencia.
En esta lección verá WritableKeyPath para structs y ReferenceWritableKeyPath para clases, además de cómo el subíndice [keyPath:] se vuelve asignable.
struct Person {
var name: String
var age: Int
}
let writable: WritableKeyPath<Person, Int> = \Person.age
print(type(of: writable))WritableKeyPath para tipos por valor
Un WritableKeyPath apunta a una propiedad almacenada mutable de un tipo por valor. Para establecerla mediante la ruta, la propia instancia debe ser una var, porque modificar una propiedad de un struct modifica el valor completo.
Use el subíndice [keyPath:] en el lado izquierdo de una asignación para escribir.
struct Person {
var name: String
var age: Int
}
var alice = Person(name: "Alice", age: 30)
let agePath = \Person.age
alice[keyPath: agePath] = 31
print(alice.age)Por qué la instancia debe ser una var
En los tipos por valor, escribir mediante una ruta de claves modifica una copia en el mismo lugar. Si la instancia es una let, no hay nada que modificar, por lo que la asignación no compilará.
La regla es la misma que para la modificación normal de propiedades: solo puede establecer la propiedad almacenada de un struct cuando este se encuentra en una variable.
struct Point {
var x: Int
var y: Int
}
var p = Point(x: 1, y: 2)
p[keyPath: \Point.x] = 10
p[keyPath: \Point.y] = 20
print(p)Un helper genérico para establecer valores
Como una ruta de claves modificable captura qué propiedad se debe cambiar, puede escribir una función genérica que actualice cualquier propiedad de cualquier tipo por valor. Pase la instancia como inout para que el cambio se escriba de vuelta.
Esta es la base de pequeñas utilidades de actualización funcional.
func update<Root, Value>(_ root: inout Root, _ path: WritableKeyPath<Root, Value>, to value: Value) {
root[keyPath: path] = value
}
struct Person { var name: String; var age: Int }
var bob = Person(name: "Bob", age: 40)
update(&bob, \.age, to: 41)
print(bob.age)ReferenceWritableKeyPath para clases
Para las clases, Swift proporciona ReferenceWritableKeyPath. Como una instancia de clase es una referencia, puede escribir mediante ella incluso cuando la instancia está almacenada en una constante let; la referencia no cambia, solo lo hace el objeto al que apunta.
Esta es la diferencia clave respecto a las rutas de claves modificables de los tipos por valor.
class Counter {
var value: Int = 0
}
let counter = Counter()
let path: ReferenceWritableKeyPath<Counter, Int> = \Counter.value
counter[keyPath: path] = 5
print(counter.value)Referencia let, objeto mutable
Observe que la instancia de la clase siguiente es una let, pero aun así podemos establecer su propiedad mediante la ruta de claves. Con un struct esto produciría un error de compilación.
Esto se debe a que modificar una propiedad de una clase no requiere que la referencia sea mutable, solo que lo sea la propiedad.
class Profile {
var nickname: String = ""
}
let profile = Profile()
let nickPath = \Profile.nickname
profile[keyPath: nickPath] = "Ace"
print(profile.nickname)La jerarquía de tipos de las rutas de claves
Los tipos de rutas de claves modificables forman una jerarquía. ReferenceWritableKeyPath es un subtipo de WritableKeyPath, que a su vez es un subtipo de KeyPath. Por tanto, una ruta de claves más específica se puede usar en cualquier lugar donde se espere una más general.
Esto significa que puede pasar un ReferenceWritableKeyPath a una función que solo necesita leer mediante un KeyPath.
class Box { var size: Int = 1 }
func readSize(_ box: Box, _ path: KeyPath<Box, Int>) -> Int {
box[keyPath: path]
}
let writable: ReferenceWritableKeyPath<Box, Int> = \Box.size
print(readSize(Box(), writable))Actualizar tipos por valor anidados
Las rutas de claves modificables se pueden encadenar a través de structs anidados. Al establecer una propiedad profundamente anidada, se reescribe cada valor contenedor a lo largo de la cadena, todo en una sola asignación.
Aquí cambiamos la ciudad dentro de una dirección anidada.
struct Address { var city: String }
struct Person { var name: String; var address: Address }
var carol = Person(name: "Carol", address: Address(city: "Oslo"))
carol[keyPath: \Person.address.city] = "Bergen"
print(carol.address.city)Aplicar varias actualizaciones
Como las rutas de claves modificables son valores, puede almacenar una lista de actualizaciones como pares de ruta de claves y valor, y aplicarlas en un bucle. Esto constituye un pequeño sistema de parches.
Aquí aplicamos dos cambios a un struct de configuración.
struct Settings { var volume: Int; var brightness: Int }
var settings = Settings(volume: 5, brightness: 5)
func apply(_ s: inout Settings, _ path: WritableKeyPath<Settings, Int>, _ v: Int) {
s[keyPath: path] = v
}
apply(&settings, \.volume, 8)
apply(&settings, \.brightness, 3)
print(settings)Configuración al estilo de binding
Un uso habitual en situaciones reales es un helper de configuración que establece una propiedad en un objeto recién creado y lo devuelve, lo que permite un estilo fluido. Con las clases, esto funciona con un resultado let.
Aquí establecemos el texto de una etiqueta mediante una ruta de claves modificable de referencia.
class Label { var text: String = "" }
func configure<T: AnyObject, V>(_ object: T, _ path: ReferenceWritableKeyPath<T, V>, _ value: V) -> T {
object[keyPath: path] = value
return object
}
let label = configure(Label(), \.text, "Hello")
print(label.text)Elegir el tipo de ruta de claves adecuado
Use KeyPath cuando solo vaya a leer, WritableKeyPath para establecer una propiedad de un tipo por valor almacenado en una var, y ReferenceWritableKeyPath para establecer una propiedad de una clase incluso mediante una let.
Elegir el tipo más específico que encaje mantiene sus API fieles a si leen o modifican datos.
struct S { var n: Int }
class C { var n: Int = 0 }
let read: KeyPath<S, Int> = \S.n
let writeStruct: WritableKeyPath<S, Int> = \S.n
let writeClass: ReferenceWritableKeyPath<C, Int> = \C.n
print(type(of: read), type(of: writeStruct), type(of: writeClass))Comprobación rápida: rutas de claves modificables
Recuerde qué tipo de ruta de claves permite establecer una propiedad de clase incluso cuando la instancia es una constante let.
Resumen: rutas de claves modificables y de referencia
Ha aprendido a escribir mediante rutas de claves:
WritableKeyPathestablece una propiedad almacenada de un tipo por valor y requiere una instanciavar.ReferenceWritableKeyPathestablece una propiedad de una clase y funciona incluso mediante unalet.- El subíndice
[keyPath:]aparece en el lado izquierdo de una asignación para escribir. - Los tipos forman una jerarquía, por lo que una ruta de claves modificable puede sustituir a una de solo lectura.
- Los setters genéricos
inouty los helpers de configuración se construyen sobre estos conceptos.
A continuación verá @dynamicMemberLookup, que usa rutas de claves para ofrecer acceso con sintaxis de punto a datos dinámicos.
struct Person { var name: String; var age: Int }
var dave = Person(name: "Dave", age: 27)
dave[keyPath: \Person.age] = 28
print("Updated age: \(dave.age)")Preguntas frecuentes
¿La lección «KeyPaths modificables y de referencia» es gratis?
Sí — el texto completo de «KeyPaths modificables y de referencia» 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 «KeyPaths modificables y de referencia»?
Lea y escriba mediante rutas de claves. 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 «KeyPaths modificables y de referencia»?
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
- Fundamentos de KeyPath
- Uso de KeyPaths en colecciones
- KeyPaths modificables y de referencia
- @dynamicMemberLookup