KeyPaths Graváveis e de Referência
Leia e escreva por meio de caminhos de chave.
KeyPaths Graváveis e de Referência é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 4 aulas no total.
Caminhos de chave somente leitura e graváveis
Um KeyPath simples só pode ler um valor. Para escrever por meio de um caminho de chave, você precisa de uma variante gravável. Swift tem duas delas: uma para tipos de valor e outra para tipos de referência.
Esta lição aborda WritableKeyPath para estruturas e ReferenceWritableKeyPath para classes, além de mostrar como o subscrito [keyPath:] se torna atribuível.
struct Person {
var name: String
var age: Int
}
let writable: WritableKeyPath<Person, Int> = \Person.age
print(type(of: writable))WritableKeyPath para tipos de valor
Um WritableKeyPath aponta para uma propriedade armazenada e mutável de um tipo de valor. Para definir seu valor por meio dele, a própria instância precisa ser uma var, pois alterar uma propriedade de uma estrutura altera o valor inteiro.
Use o subscrito [keyPath:] no lado esquerdo de uma atribuição para escrever.
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 que a instância precisa ser uma var
Para tipos de valor, escrever por meio de um caminho de chave altera uma cópia no próprio lugar. Se a instância for uma let, não haverá nada que possa ser alterado, portanto a atribuição não será compilada.
A regra é igual à mutação normal de uma propriedade: você só pode definir a propriedade armazenada de uma estrutura quando a estrutura está contida em uma variável.
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)Uma função auxiliar genérica para atribuição
Como um caminho de chave gravável registra qual propriedade deve ser alterada, você pode escrever uma função genérica que atualiza qualquer propriedade de qualquer tipo de valor. Passe a instância como inout para que a alteração seja gravada de volta.
Essa é a base de pequenos utilitários de atualização 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 classes
Para classes, Swift fornece ReferenceWritableKeyPath. Como uma instância de classe é uma referência, você pode escrever por meio dela mesmo quando a instância está contida em uma constante let; a referência não muda, apenas o objeto para o qual ela aponta.
Essa é a principal diferença em relação aos caminhos de chave graváveis de tipos de valor.
class Counter {
var value: Int = 0
}
let counter = Counter()
let path: ReferenceWritableKeyPath<Counter, Int> = \Counter.value
counter[keyPath: path] = 5
print(counter.value)Referência constante, objeto mutável
Observe que a instância da classe abaixo é uma let, mas ainda podemos definir sua propriedade por meio do caminho de chave. Com uma estrutura, isso geraria um erro de compilação.
Isso ocorre porque alterar uma propriedade de classe não exige que a referência seja mutável, apenas que a propriedade seja.
class Profile {
var nickname: String = ""
}
let profile = Profile()
let nickPath = \Profile.nickname
profile[keyPath: nickPath] = "Ace"
print(profile.nickname)A hierarquia de tipos dos caminhos de chave
Os tipos de caminho de chave graváveis formam uma hierarquia. ReferenceWritableKeyPath é um subtipo de WritableKeyPath, que é um subtipo de KeyPath. Portanto, um caminho de chave mais específico pode ser usado onde se espera um mais geral.
Isso significa que você pode passar um ReferenceWritableKeyPath para uma função que só precisa ler por meio de um 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))Atualizando tipos de valor aninhados
Os caminhos de chave graváveis podem ser encadeados por estruturas aninhadas. Definir uma propriedade profundamente aninhada reescreve cada valor que a envolve ao longo da cadeia, tudo em uma única atribuição.
Aqui alteramos a cidade dentro de um endereço aninhado.
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)Aplicando várias atualizações
Como os caminhos de chave graváveis são valores, você pode armazenar uma lista de atualizações como pares de caminho de chave e valor e aplicá-las em um laço. Esse é um pequeno sistema de aplicação de alterações.
Aqui aplicamos duas alterações a uma estrutura de configurações.
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)Configuração no estilo de vinculação
Um uso comum no mundo real é uma função auxiliar de configuração que define uma propriedade em um objeto recém-criado e o retorna, permitindo um estilo fluente. Com classes, isso funciona sobre um resultado let.
Aqui definimos o texto de um rótulo por meio de um caminho de chave gravável de referência.
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)Escolhendo o tipo certo de caminho de chave
Use KeyPath quando você apenas lê, WritableKeyPath para definir uma propriedade de um tipo de valor armazenado em uma var e ReferenceWritableKeyPath para definir uma propriedade de uma classe mesmo por meio de uma let.
Escolher o tipo mais específico que se encaixa mantém suas APIs claras quanto ao fato de lerem ou alterarem valores.
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))Verificação rápida: caminhos de chave graváveis
Lembre-se de qual tipo de caminho de chave permite definir uma propriedade de classe mesmo quando a instância é uma constante let.
Recapitulação: caminhos de chave graváveis e de referência
Você aprendeu a escrever por meio de caminhos de chave:
WritableKeyPathdefine uma propriedade armazenada de um tipo de valor, exigindo uma instânciavar.ReferenceWritableKeyPathdefine uma propriedade de uma classe e funciona mesmo por meio de umalet.- O subscrito
[keyPath:]aparece no lado esquerdo de uma atribuição para escrever. - Os tipos formam uma hierarquia, portanto um caminho de chave gravável pode substituir um caminho somente leitura.
- Funções auxiliares genéricas de atribuição
inoute funções auxiliares de configuração se baseiam nesses recursos.
A seguir, você verá @dynamicMemberLookup, que usa caminhos de chave para oferecer acesso com sintaxe de ponto a dados 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)")Perguntas Frequentes
A aula “KeyPaths Graváveis e de Referência” é grátis?
Sim — o texto completo de “KeyPaths Graváveis e de Referência” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 4 aulas no total.
O que vou aprender em “KeyPaths Graváveis e de Referência”?
Leia e escreva por meio de caminhos de chave. Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Swift Academy?
Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “KeyPaths Graváveis e de Referência”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Swift Academy?
Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Noções Básicas de KeyPath
- Uso de KeyPaths em Coleções
- KeyPaths Graváveis e de Referência
- @dynamicMemberLookup