KeyPath: əsas anlayışlar və tipli giriş

Müəllif: IT Sectr Dərc olunub: 2026-06-18 Oxuma vaxtı: 10 dəq

KeyPath — Swift-də obyektin xassəsinə tipli yoldur, birinci dərəcəli dəyər kimi təqdim olunur. KVC-dəki (Key-Value Coding) sətir açarlarından fərqli olaraq, KeyPath kompilyator tərəfindən yığma mərhələsində yoxlanılır: kompilyator kök obyektin tipini, xassənin tipini bilir və yolun mövcud olduğuna zəmanət verə bilər. KeyPath Combine-də reaktiv bağlama, SwiftUI-də ikitərəfli bindiq və standart kitabxanada kolleksiyaların sıralanması və filtrlənməsi üçün istifadə olunur. Apple Developer, 2025-ə görə, KeyPath Swift-də funksional proqramlaşdırma üçün fundamental tikinti blokudur.

Əsas məqamlar

  • KeyPath — kompilyator tərəfindən yoxlanılan, xassəyə tipli yol
  • WritableKeyPath — yazmaq imkanı olan xassələr üçün KeyPath alt tipi
  • ReferenceWritableKeyPath — istinad tiplərinin dəyişdirilə bilən xassələri üçün
  • Combine KeyPath-dən naşirləri obyektlərin xassələrinə bağlamaq üçün istifadə edir
  • AnyKeyPath — kolleksiyalarda KeyPath saxlamaq üçün type-erased variant

Swift-də KeyPath nədir?

KeyPath — Swift standart kitabxanasından olan tip, obyektin xassəsinə yolu təmsil edir. Xassəyə nöqtə vasitəsilə əl ilə girişdən (object.property) və ya sətir açarından (value(forKey:)) fərqli olaraq, KeyPath birinci dərəcəli obyektdir: onu arqument kimi ötürmək, dəyişəndə saxlamaq və birləşdirmək olar.

KeyPath sintaksisi

KeyPath tərs işarə və xassəyə yol vasitəsilə yazılır: \Person.name. Yol iç-içə ola bilər: \Person.address.city. Kompilyator Person-un name xassəsinə malik olduğunu və name-in həqiqətən String tipində olduğunu yoxlayır. Xassə mövcud deyilsə və ya tip səhvdirsə, kod kompilyasiya olunmur.

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

// KeyPath (yalnız oxumaq üçün)
let namePath: KeyPath<Person, String> = \Person.name
let person = Person(name: "Alice", age: 30, isActive: true)
let name = person[keyPath: namePath]

KeyPath vasitəsilə xassəyə giriş object[keyPath: path] subskripti ilə həyata keçirilir. ReadOnly xassələri üçün KeyPath istifadə olunur. Xassə dəyişkəndirsə (var), WritableKeyPath mövcuddur. İstinad tipləri üçün — ReferenceWritableKeyPath, KeyPath vasitəsilə xassəni dəyişməyə imkan verir.

KeyPath iyerarxiyası: WritableKeyPath və ReferenceWritableKeyPath

KeyPath xassəyə giriş səviyyəsini əks etdirən alt tiplər iyerarxiyasına malikdir. Əsas iyerarxiya: AnyKeyPath → PartialKeyPath → KeyPath → WritableKeyPath → ReferenceWritableKeyPath. Hər alt tip imkanlar əlavə edir.

KeyPath giriş səviyyələri

KeyPath — yalnız oxumaq. WritableKeyPath — dəyər tipləri (struct) üçün oxumaq və yazmaq. ReferenceWritableKeyPath — istinad tipləri (class) üçün oxumaq və yazmaq. Swift kontekstdən asılı olaraq avtomatik olaraq düzgün alt tipi seçir.

TipGirişObyektin tipiDəyişmə
KeyPathReadOnlyİstənilənXeyr
WritableKeyPathReadWriteValue-tipi (inout)Mutating konteksti ilə
ReferenceWritableKeyPathReadWriteReference-tipiBirbaşa təyin etmə
swift
// WritableKeyPath dəyər tipi üçün
var mutablePerson = Person(name: "Bob", age: 25, isActive: false)
let writablePath: WritableKeyPath<Person, Bool> = \Person.isActive
mutablePerson[keyPath: writablePath] = true

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

Vacib fərq: dəyər tipləri üçün KeyPath vasitəsilə təyin etmə var (inout konteksti) tələb edir, istinad tipləri üçün isə dəyişkən xassə. Bu Swift-in ümumi semantikasına uyğundur: dəyər tipləri dəyərlə ötürülür, buna görə dəyişiklik konteynerin mutasiyasını tələb edir.

KeyPath Combine və SwiftUI-də

KeyPath Combine və SwiftUI-də mərkəzi rol oynayır. Combine-də assign operatoru naşirin dəyərini obyektin xassəsinə bağlamaq üçün KeyPath istifadə edir. SwiftUI-də Binding model və görünüşün ikitərəfli əlaqələndirilməsi üçün KeyPath istifadə edir.

Combine-də Assign

assign(to:on:) operatoru ReferenceWritableKeyPath və obyekt qəbul edir. Naşir dəyər göndərdikdə, avtomatik olaraq göstərilən xassəyə yazılır. Bu, əl ilə təyin etmədən vəziyyətin idarə edilməsinin deklarativ üsuludur.

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-də @Binding ana və uşaq View-i birləşdirmək üçün KeyPath istifadə edir. Ana Binding(get:set:) və ya proyeksiya ($) vasitəsilə yaradılmış Binding ötürür. KeyPath SwiftUI-yə dəyişiklikləri avtomatik izləməyə və UI-ni lazımsız səy olmadan yeniləməyə imkan verir.

Sıralama və filtrasiya üçün KeyPath istifadəsi

KeyPath çevik və tip təhlükəsiz sıralama və filtrasiya funksiyaları yazmağa imkan verir. Hər dəfə closure ötürmək əvəzinə, kolleksiyanı sıralamaq istədiyiniz xassəyə KeyPath ötürə bilərsiniz. Bu kodu təmizləyir və təkrarlanmanı azaldır.

KeyPath üzrə sıralama üçün generic funksiya

sorted funksiyası KeyPath qəbul edir, burada Value: Comparable. Bu, sıraladığımız xassənin müqayisəni dəstəklədiyinə zəmanət verir. Kompilyator bunu yığma mərhələsində yoxlayır.

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)

Belə bir tətbiq closure yazmadan istənilən Comparable xassəsi üzrə sıralayır. Soyad üzrə sıralamaq üçün KeyPath-i dəyişmək kifayətdir: \Person.lastName. Qeyri-standart açar üzrə sıralamaq lazımdırsa (məsələn, adın uzunluğu), daxildə map istifadə olunur — proqramçı qeyri-standart hallar üçün öz closure-nu yaza bilər.

Type-erased AnyKeyPath

AnyKeyPath — KeyPath iyerarxiyasında əsas tipdir, kök və dəyərin konkret tipləri haqqında məlumatı silir. AnyKeyPath hansı obyekt tipində çağırıldığını və hansı dəyər tipini qaytardığını bilmir. Bu, müxtəlif KeyPath-ləri kolleksiyalarda saxlamaq və refleksiya üçün faydalıdır.

AnyKeyPath tətbiqi

AnyKeyPath müxtəlif tiplərin müxtəlif xassələrinə yolların siyahısını saxlamaq lazım olduqda istifadə olunur. Məsələn, UI konfiquratorunda, hər yol müəyyən bir xassəni konfiqurasiya edir və xassə tipləri fərqlənə bilər. AnyKeyPath bütün yollarla vahid şəkildə işləməyə imkan verir.

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 vasitəsilə xassələri konfiqurasiya etməyə imkan verir

AnyKeyPath dəyəri çıxararkən tip çevirmə tələb edir, çünki konkret tip silinib. Tam tip təhlükəsizliyi üçün həmişə tipli KeyPath üstünlük təşkil edir. AnyKeyPath — tiplərin həqiqətən kompilyasiya mərhələsində məlum olmadığı hallar üçün alətdir, məsələn, serializasiya və ya refleksiya zamanı.

KeyPath performansı vs sətir açarları

KeyPath KVC-nin (value(forKey:)) sətir açarlarından əhəmiyyətli dərəcədə daha məhsuldardır. Sətir açarları Objective-C runtime mexanizmi vasitəsilə hesablanır, sətrin pars edilməsi, runtimedə axtarış və tip çevirmə daxildir. KeyPath — Swift-in nativ strukturlarına əsaslanan statik mexanizmdir.

Performans müqayisəsi

Testlərə görə, KeyPath xassələrə girişdə value(forKey:) -dən orta hesabla 10-20 dəfə sürətlidir. Fərq runtime axtarışının və dinamik dispetçerin olmaması ilə bağlıdır. KeyPath kompilyatorun kifayət qədər optimallaşdırılması ilə birbaşa yaddaşdakı xassə offsetinə müraciət edir.

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

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

KVC nəinki daha yavaş, həm də tipcə təhlükəsiz deyil: “name” sətri mövcud olmaya bilər, as! String çevirməsi isə çökə bilər. KeyPath xassənin mövcudluğuna və tipin düzgünlüyünə kompilyasiya mərhələsində zəmanət verir. Performans baxımından kritik yerlər üçün (animasiyalar, minlərlə elementdən ibarət siyahı) KeyPath yeganə düzgün seçimdir.

Tez-tez verilən suallar

Swift-də KeyPath nədir sadə sözlərlə?

KeyPath — adi dəyər kimi ötürülə bilən obyektin xassəsinə göstəricidir. person.name yazmaq əvəzinə, \Person.name yolunu yaradır və onu istənilən Person nümunəsində xassəni oxumaq və ya yazmaq üçün istifadə edirsiniz.

KeyPath, WritableKeyPath və ReferenceWritableKeyPath arasında nə fərq var?

KeyPath — yalnız oxumaq üçün. WritableKeyPath — dəyər tiplərinin (struct) inout konteksti vasitəsilə oxunması və yazılması üçün. ReferenceWritableKeyPath — əlavə şərtlər olmadan istinad tiplərinin (class) oxunması və yazılması üçün.

Swift-də KeyPath harada tətbiq olunur?

KeyPath geniş şəkildə Combine (assign(to:on:)), SwiftUI (Binding, FocusState), kolleksiyaların sıralanması (sorted(by:)), Core Data (NSSortDescriptor) və iç-içə xassələrə təhlükəsiz giriş üçün istifadə olunur.

KeyPath value(forKey:) -dən təhlükəsizdirmi?

Bəli, KeyPath tam tip təhlükəsizdir. Yoldakı səhv (səhv yazı, yanlış tip) runtime-da deyil, kompilyasiya mərhələsində aşkar edilir. value(forKey:) sətirlərdən istifadə edir və açar mövcud deyilsə, NSUndefinedKeyException ilə çökə bilər.

KeyPath dinamik yaradıla bilərmi?

Birbaşa — yox, Swift sətirdən dinamik KeyPath yaradılmasını dəstəkləmir. Bununla belə, statik əldə edilmiş KeyPath-ləri saxlamaq və ötürmək üçün AnyKeyPath istifadə edilə bilər. Sətir üzrə xassələrə dinamik giriş üçün Objective-C runtime ilə value(forKey:) istifadə edin.

Nəticə

  • KeyPath — birinci dərəcəli dəyər tipi kimi təqdim olunan, xassəyə tipli yol
  • İyerarxiya KeyPath müxtəlif giriş səviyyələri üçün WritableKeyPath və ReferenceWritableKeyPath-i əhatə edir
  • Combine və SwiftUI reaktiv bağlamalar və bindiqlər üçün KeyPath-dən aktiv istifadə edir
  • Sıralama və filtrasiya KeyPath vasitəsilə kodun oxunaqlılığını və tip təhlükəsizliyini artırır
  • AnyKeyPath — kolleksiyalarda müxtəlif KeyPath-ləri saxlamaq üçün type-erased variant
  • Performans KeyPath value(forKey:) -dən 10-20 dəfə yüksəkdir

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun