My notes on keypath

  • KeyPath: Provides read-only access to a property.
  • WritableKeyPath: Provides readwrite access to a mutable property with value semantics (so the instance in question also needs to be mutable for writes to be allowed).
  • ReferenceWritableKeyPath: Can only be used with reference types (such as instances of a class), and provides readwrite access to any mutable property.


struct Starship {
    var name: String
    var maxWarp: Double

let voyager = Starship(name: “Voyager”, maxWarp: 9.975) Keypaths let us refer to the name or maxWarp properties without reading them directly, like this:

let nameKeyPath = \
let warpKeyPath = \Starship.maxWarp

If you want to read those keypaths on a specific starship, Swift will return you the actual values attached to those properties:

let nameKeyPath = \
let warpKeyPath = \Starship.maxWarp

print(voyager[keyPath: nameKeyPath])
print(voyager[keyPath: warpKeyPath])


When using KeyPaths within an object definition itself, you can omit the definition name, like this:

class Doll {
  func getMaker() -> String {
    return self[keyPath: \.maker]


func getPropertyValue(in doll: Doll2, keyPath: KeyPath<Doll2, String>) -> String {
  return doll[keyPath: keyPath]

Advance usage:

Let’s create a generic type called CellConfigurator, and since we want to render different data for different models, we’ll give it a set of key path-based properties — one for each piece of data that we’re looking to render:

struct CellConfigurator<Model> {
    let titleKeyPath: KeyPath<Model, String>
    let subtitleKeyPath: KeyPath<Model, String>
    let imageKeyPath: KeyPath<Model, UIImage?>

    func configure(_ cell: UITableViewCell, for model: Model) {
        cell.textLabel?.text = model[keyPath: titleKeyPath]
        cell.detailTextLabel?.text = model[keyPath: subtitleKeyPath]
        cell.imageView?.image = model[keyPath: imageKeyPath]

The beauty of the above approach is that we can now easily specialize our generic CellConfigurator for each model using the same lightweight key path syntax from before — like this:

let songCellConfigurator = CellConfigurator<Song>(
    titleKeyPath: \.name,
    subtitleKeyPath: \.artistName,
    imageKeyPath: \.albumArtwork

let playlistCellConfigurator = CellConfigurator<Playlist>(
    titleKeyPath: \.title,
    subtitleKeyPath: \.authorName,
    imageKeyPath: \.artwork


We have three read-only key paths.

KeyPath ParialKeyPath AnyKeyPath And two writable key paths.

WritableKeyPath ReferenceWritableKeyPath I will only focus on three basic types of key paths in this article.

KeyPath: A read-only access to a property. Root type can be both value/reference semantics. WritableKeyPath: Provides read-write access to a mutable property with value semantics (such as struct and enum). ReferenceWritableKeyPath: Provides reading and writing to a mutable property with reference semantics (such as class). We won’t talk about ParialKeyPath and AnyKeyPath here since it is another type-erased variation of KeyPath.

KeyPath resources