KeyPath: temel kavramlar ve türlenmiş erişim

Yazar: IT Sectr Yayınlanma: 2026-06-18 Okuma süresi: 10 dk

KeyPath, Swift'te bir nesnenin özelliğine türlenmiş bir yoldur ve birinci sınıf bir değer olarak temsil edilir. KVC'deki (Key-Value Coding) dize anahtarlarının aksine, KeyPath derleme zamanında derleyici tarafından kontrol edilir: derleyici kök nesnenin türünü, özelliğin türünü bilir ve yolun var olduğunu garanti edebilir. KeyPath, Combine'da reaktif bağlama için, SwiftUI'de iki yönlü bağlama için ve standart kütüphanede koleksiyonları sıralama ve filtreleme için kullanılır. Apple Developer, 2025'e göre KeyPath, Swift'te işlevsel programlama için temel bir yapı taşıdır.

Önemli Noktalar

  • KeyPath — bir özelliğe türlenmiş yol, derleyici tarafından doğrulanır
  • WritableKeyPath — yazma erişimli özellikler için KeyPath'in alt türü
  • ReferenceWritableKeyPath — başvuru türlerinin değiştirilebilir özellikleri için
  • Combine, yayıncıları nesne özelliklerine bağlamak için KeyPath kullanır
  • AnyKeyPath — koleksiyonlarda KeyPath saklamak için tür silinmiş değişken

Swift'te KeyPath Nedir?

KeyPath, bir nesnenin özelliğine giden yolu temsil eden Swift standart kütüphanesinden bir türdür. Nokta gösterimi (object.property) veya dize anahtarı (value(forKey:)) ile bir özelliğe manuel olarak erişmenin aksine, KeyPath birinci sınıf bir nesnedir: argüman olarak iletilebilir, bir değişkende saklanabilir ve birleştirilebilir.

KeyPath Sözdizimi

Bir KeyPath, ters eğik çizgi ve özelliğe giden yol ile yazılır: \Person.name. Yol iç içe olabilir: \Person.address.city. Derleyici, Person'un name adlı bir özelliği olduğunu ve name'in gerçekten bir String olduğunu doğrular. Özellik yoksa veya tür yanlışsa, kod derlenmez.

swift
struct Person: Codable {
    let name: String
    let age: Int
    var isActive: Bool
}

// KeyPath (salt okunur)
let namePath: KeyPath<Person, String> = \Person.name
let person = Person(name: "Alice", age: 30, isActive: true)
let name = person[keyPath: namePath]

KeyPath aracılığıyla bir özelliğe erişim, object[keyPath: path] alt simgesi aracılığıyla yapılır. Salt okunur özellikler için KeyPath kullanılır. Özellik değiştirilebilir (var) ise, WritableKeyPath kullanılabilir. Başvuru türleri için, ReferenceWritableKeyPath, KeyPath aracılığıyla özelliği doğrudan değiştirmeye izin verir.

KeyPath Hiyerarşisi: WritableKeyPath ve ReferenceWritableKeyPath

KeyPath, özelliğe erişim seviyesini yansıtan bir alt tür hiyerarşisine sahiptir. Temel hiyerarşi şöyledir: AnyKeyPath → PartialKeyPath → KeyPath → WritableKeyPath → ReferenceWritableKeyPath. Her alt tür yetenekler ekler.

KeyPath Erişim Seviyeleri

KeyPath — salt okunur. WritableKeyPath — değer türleri (struct) için okuma ve yazma. ReferenceWritableKeyPath — başvuru türleri (class) için okuma ve yazma. Swift, bağlama göre otomatik olarak doğru alt türü seçer.

TürErişimNesne TürüDeğişiklik
KeyPathSalt okunurHerhangiHayır
WritableKeyPathOkuma ve yazmaDeğer türü (inout)Mutating bağlamı aracılığıyla
ReferenceWritableKeyPathOkuma ve yazmaBaşvuru türüDoğrudan atama
swift
// Değer türü için WritableKeyPath
var mutablePerson = Person(name: "Bob", age: 25, isActive: false)
let writablePath: WritableKeyPath<Person, Bool> = \Person.isActive
mutablePerson[keyPath: writablePath] = true

// Sınıf için ReferenceWritableKeyPath
class User: NSObject {
    @objc dynamic var name: String = ""
}
let user = User()
let refPath: ReferenceWritableKeyPath<User, String> = \User.name
user[keyPath: refPath] = "Charlie"

Önemli bir fark: değer türleri için, KeyPath aracılığıyla ayarlama var (inout bağlamı) gerektirirken, başvuru türleri için yalnızca değiştirilebilir bir özellik yeterlidir. Bu, Swift'in genel anlambilimiyle uyumludur: değer türleri değer olarak iletilir, bu nedenle değişiklik kapsayıcının değiştirilebilirliğini gerektirir.

Combine ve SwiftUI'de KeyPath

KeyPath, Combine ve SwiftUI'de merkezi bir rol oynar. Combine'da, assign operatörü bir yayıncının değerini bir nesnenin özelliğine bağlamak için KeyPath kullanır. SwiftUI'de, Binding, model ve görünüm arasında iki yönlü bağlantı için KeyPath kullanır.

Combine'da Assign

assign(to:on:) operatörü bir ReferenceWritableKeyPath ve bir nesne kabul eder. Yayıncı bir değer yaydığında, otomatik olarak belirtilen özelliğe yazılır. Bu, manuel atamalar olmadan durumu yönetmenin bildirimsel bir yoludur.

swift
import Combine

class SettingsViewModel: ObservableObject {
    @Published var volume: Float = 0.5
    var cancellables = Set<AnyCancellable>()
    
    func bindSlider(publisher: AnyPublisher<Float, Never>) {
        publisher
            .assign(to: \SettingsViewModel.volume, on: self)
            .store(in: &cancellables)
    }
}

SwiftUI'de, @Binding bir üst ve alt görünümü bağlamak için KeyPath kullanır. Üst, Binding(get:set:) veya izdüşüm ($) aracılığıyla oluşturulan bir Binding iletir. KeyPath, SwiftUI'nin değişiklikleri otomatik olarak izlemesine ve ekstra çaba harcamadan arayüzü güncellemesine olanak tanır.

Sıralama ve Filtreleme İçin KeyPath Kullanımı

KeyPath, esnek ve tür güvenli sıralama ve filtreleme işlevleri yazmayı mümkün kılar. Her seferinde bir closure iletmek yerine, koleksiyonu sıralamak istediğiniz özelliğe bir KeyPath iletebilirsiniz. Bu, kodu daha temiz hale getirir ve tekrarı azaltır.

KeyPath'e Göre Genel Sıralama İşlevi

sorted işlevi, Value: Comparable olmak üzere KeyPath kabul eder. Bu, sıralama özelliğinin karşılaştırmayı desteklemesini garanti eder. Derleyici bunu derleme zamanında kontrol eder.

swift
extension Sequence {
    func sorted<Value: Comparable>(
        by keyPath: KeyPath<Element, Value>,
        ascending: Bool = true
    ) -> [Element] {
        ascending
            ? self.sorted { $0[keyPath: keyPath] < $1[keyPath: keyPath] }
            : self.sorted { $0[keyPath: keyPath] > $1[keyPath: keyPath] }
    }
}

let sortedByName = people.sorted(by: \Person.name)
let sortedByAgeDesc = people.sorted(by: \Person.age, ascending: false)

Bu uygulama, closure yazmadan herhangi bir Comparable özelliğine göre sıralar. Soyadına göre sıralamak için, KeyPath'i değiştirmeniz yeterlidir: \Person.lastName. Özel bir anahtara göre sıralama gerekiyorsa (orneğin, ad uzunluğu), dahili olarak map kullanılır — geliştirici, standart olmayan durumlar için kendi closure'ını yazabilir.

Tür Silinmiş AnyKeyPath

AnyKeyPath, belirli kök ve değer türleri hakkındaki bilgileri silen KeyPath hiyerarşisindeki temel türdür. AnyKeyPath, hangi nesne türünde çağrıldığını veya hangi değer türünü döndürdüğünü bilmez. Bu, heterojen KeyPath'leri koleksiyonlarda saklamak ve yansıma için kullanışlıdır.

AnyKeyPath Kullanımı

AnyKeyPath, farklı türlerdeki farklı özelliklere yolların bir listesini saklamanız gerektiğinde kullanılır. Örneğin, her yolun belirli bir özelliği yapılandırdığı ve özellik türlerinin farklılık gösterebildiği bir UI yapılandırıcısında. AnyKeyPath, tüm yollarla tek tip çalışmaya olanak tanır.

swift
protocol Configurable {
    func apply(_ keyPath: any PartialKeyPath<Self>, value: any)
}

extension Configurable {
    func configure(_ pairs: (any KeyPath<Self, any>, any)...) {
        for (path, value) in pairs {
            apply(path, value: value)
        }
    }
}

extension Person: Configurable { }
// AnyKeyPath aracılığıyla özellikleri yapılandırmaya izin verir

AnyKeyPath, değer alınırken tür dönüşümü gerektirir, çünkü belirli tür silinmiştir. Tam tür güvenliği için, türlenmiş bir KeyPath her zaman tercih edilir. AnyKeyPath, serileştirme veya yansıma gibi türlerin derleme zamanında gerçekten bilinmediği durumlar için bir araçtır.

KeyPath Performansı vs Dize Anahtarları

KeyPath, KVC dize anahtarlarından (value(forKey:)) önemli ölçüde daha verimlidir. Dize anahtarları, dize ayrıştırma, çalışma zamanı araması ve tür dönüşümü dahil olmak üzere Objective-C çalışma zamanı mekanizması aracılığıyla çözülür. KeyPath, yerel Swift yapılarına dayanan statik bir mekanizmadır.

Performans Karşılaştırması

Kıyaslamalara göre, KeyPath özelliklere erişim için value(forKey:)'den ortalama 10-20 kat daha hızlıdır. Fark, çalışma zamanı araması ve dinamik gönderimin olmamasından kaynaklanmaktadır. KeyPath, yeterli derleyici optimizasyonuyla bellektekai özellik ofsetine doğrudan erişir.

swift
func readWithKeyPath(person: Person) -> String {
    person[keyPath: \Person.name]
}

func readWithKVC(person: Person) -> String {
    person.value(forKey: "name") as! String
}

KVC yalnızca daha yavaş olmakla kalmaz, aynı zamanda tür açısından güvensizdir: “name” dizesi mevcut olmayabilir ve as! String dönüşümü çökebilir. KeyPath, derleme zamanında özelliğin varlığını ve tür doğruluğunu garanti eder. Performans açısından kritik bölümler (animasyonlar, binlerce öğeli listeler) için KeyPath tek doğru seçimdir.

Sıkça Sorulan Sorular

Basit bir ifadeyle Swift'te KeyPath nedir?

KeyPath, normal bir değer olarak iletilebilen bir nesne özelliğine bir işaretçidir. person.name yazmak yerine, \Person.name yolunu oluşturur ve herhangi bir Person örneğinde özelliği okumak veya yazmak için kullanırsınız.

KeyPath, WritableKeyPath ve ReferenceWritableKeyPath arasındaki fark nedir?

KeyPath — salt okunur. WritableKeyPath — inout bağlamı aracılığıyla değer türlerini (struct) okumak ve yazmak için. ReferenceWritableKeyPath — ek koşullar olmadan başvuru türlerini (class) okumak ve yazmak için.

Swift'te KeyPath nerede kullanılır?

KeyPath, Combine (assign(to:on:)), SwiftUI (Binding, FocusState), koleksiyon sıralama (sorted(by:)), Core Data (NSSortDescriptor) ve iç içe özelliklere güvenli erişim için yaygın olarak kullanılır.

KeyPath, value(forKey:)'den daha güvenli midir?

Evet, KeyPath tamamen tür güvenlidir. Yoldaki bir hata (yazım hatası, yanlış tür) çalışma zamanında değil, derleme zamanında yakalanır. value(forKey:) dizeleri kullanır ve anahtar mevcut değilse NSUndefinedKeyException ile çökebilir.

KeyPath dinamik olarak oluşturulabilir mi?

Doğrudan hayır — Swift, bir dizeden dinamik KeyPath oluşturmayı desteklemez. Ancak, statik olarak elde edilen KeyPath'leri saklamak ve iletmek için AnyKeyPath'i kullanabilirsiniz. Dize ile dinamik özellik erişimi için, Objective-C çalışma zamanıyla value(forKey:)'i kullanın.

Özet

  • KeyPath — bir özelliğe türlenmiş yol, birinci sınıf değer türü olarak temsil edilir
  • Hiyerarşi KeyPath, farklı erişim seviyeleri için WritableKeyPath ve ReferenceWritableKeyPath içerir
  • Combine ve SwiftUI reaktif bağlamalar için KeyPath'i aktif olarak kullanır
  • Sıralama ve filtreleme KeyPath aracılığıyla kod okunabilirliğini ve tür güvenliğini artırır
  • AnyKeyPath — koleksiyonlarda heterojen KeyPath'leri saklamak için tür silinmiş değişken
  • Performans KeyPath, value(forKey:)'den 10-20 kat daha yüksektir

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun