Published on

Swift Advanced: Swift'da KeyPaths nima va u qanday ishlaydi?

Authors

KeyPath o'zi nima?

SwiftUI da siz \.dismiss yoki \.presentationMode kabi yozuvlarni ko'p ishlatgansiz. Nega ularni doim \. bilan yozishimiz kerak? Chunki ular KeyPath hisoblanadi.

KeyPath — bu ob'ektning biror bir qismini (property'sini) bevosita emas, balki unga eltuvchi "yo'l" (path) orqali chaqirish usuli.

Oddiy misol:

struct MyDataModel {
    let id = UUID().uuidString
    let title: String
    let count: Int
    let date: Date
}

let item = MyDataModel(title: "Bir", count: 1, date: .now)

// Odatdagi chaqirish usuli:
let title1 = item.title

// KeyPath orqali chaqirish usuli:
let title2 = item[keyPath: \.title]

Bu yerda title1 ham, title2 ham bir xil natija beradi. Unda nima uchun bizga qiyin usul kerak deysizmi? Chunki bu usul Generic kod yozishda, ayniqsa massivlarni (Array) qayta ishlashda katta yordam beradi.

Nega KeyPath kerak? (Amaliy misol)

Aytaylik, bizda har xil modellardan iborat massiv bor va biz uni saralamoqchimiz (sort).

Odatda kod bunday ko'rinadi:

let array = [
    MyDataModel(title: "Uch", count: 3, date: .now),
    MyDataModel(title: "Bir", count: 1, date: .distantPast),
    MyDataModel(title: "Ikki", count: 2, date: .distantFuture)
]

// count (soni) bo'yicha saralash
let sortedArray = array.sorted { item1, item2 in
    return item1.count < item2.count
}

Bu usul yaxshi ishlaydi. Lekin biz date yoki title bo'yicha saralamoqchi bo'lsak, yana qaytadan xuddi shunday funksiya yozishimizga to'g'ri keladi.

KeyPath bilan universal saralash (Sorting Extension)

Biz massiv (Array) uchun shunday universal kod yozamizki, u har qanday modelni va har qanday xususiyatini (count, title, date) saralay olsin!

extension Array {

    // T - saralanadigan qiymat turi (u albatta Comparable, ya'ni taqqoslanadigan bo'lishi kerak)
    func sortedByKeyPath<T: Comparable>(_ keyPath: KeyPath<Element, T>, ascending: Bool = true) -> [Element] {
        self.sorted { item1, item2 in
            // KeyPath orqali qiymatlarni ajratib olamiz
            let value1 = item1[keyPath: keyPath]
            let value2 = item2[keyPath: keyPath]

            // O'sish yoki kamayish tartibiga qarab taqqoslaymiz
            return ascending ? (value1 < value2) : (value1 > value2)
        }
    }
}

Ushbu Extension dagi mo'jizani ko'ring! Biz unda bevosita count yoki title ni emas, balki qandaydir ochiq qoldirilgan yo'l (keyPath) ni ko'rsatdik. Nima berilsa, shuni saralaydi.

Universal funksiyadan foydalanish

Endi yuqoridagi ro'yxatni istalgan narsaga qarab bir qator kod bilan saralashimiz mumkin:

// Soniga (count) qarab saralash (1, 2, 3)
let sortedByCount = array.sortedByKeyPath(\.count)

// Alfavit bo'yicha (title) saralash
let sortedByTitle = array.sortedByKeyPath(\.title)

// Sanaga (date) qarab eng oxirgisidan birinchisiga qarab saralash
let sortedByDate = array.sortedByKeyPath(\.date, ascending: false)

Xulosa

Siz kundalik SwiftUI kodlarida KeyPath larni asosan Environment o'zgaruvchilarda ko'rasiz. O'z kodingizda har doim ham uni ishlatavermaysiz, lekin siz shunday toza API'lar yoki moslashuvchan funksiyalar yozmoqchi bo'lsangiz (biz yuqorida saralash uchun yozganimiz kabi), KeyPath lar haqiqiy qutqaruvchiga aylanadi.

Buy mea coffee