Published on

Swift-da Hashable protokoli nima va qanday ishlatiladi

Authors

Bu videoda Hashable protokoli ko'rib chiqiladi. SwiftUI-da ko'plab komponentlar β€” jumladan ForEach β€” modeldan noyob identifikator talab qiladi. Odatda buning uchun Identifiable ishlatiladi, lekin ba'zan Hashable qulay alternativ bo'ladi.


Hashable nima?

Hashable β€” ob'ektga noyob raqamli qiymat (hash value) beruvchi protokol. Tizim bu raqam orqali ob'ektlarni bir-biridan ajrata oladi. Hashing faqat Swift yoki SwiftUI-ga xos emas β€” bu barcha dasturlash muhitlarida keng qo'llaniladigan tushuncha.


String-da Hashable allaqachon bor

SwiftUI-da ForEach-da id: \.self ishlatilganda β€” bu String-ning Hashable-ga muvofiq kelganidan foydalaniladi:

let data: [String] = ["Bir", "Ikki", "Uch", "To'rt", "Besh"]

ScrollView {
    VStack(spacing: 40) {
        ForEach(data, id: \.self) { item in
            Text(item)
                .font(.headline)
        }
    }
}

id: \.self β€” har bir elementning o'zi ID vazifasini bajaradi. Bu faqat element Hashable bo'lganda ishlaydi. String standart holatda Hashable-ga muvofiq keladi.

Hash value-ni ko'rish

ForEach(data, id: \.self) { item in
    Text(item.hashValue.description)
        .font(.headline)
}
// Chiqadi: 1234567890123, -9876543210, ... kabi raqamlar
// Har bir string uchun noyob raqam

Bu raqamlar ilovada ko'rinmaydi va ular bilan ishlanmaydi β€” faqat tizim ulardan foydalanadi.


O'z modelingizni yaratish β€” muammo

struct MyCustomModel {
    let title: String
}

let data: [MyCustomModel] = [
    MyCustomModel(title: "Bir"),
    MyCustomModel(title: "Ikki"),
    MyCustomModel(title: "Uch"),
]

// ❌ Xato: MyCustomModel Hashable-ga muvofiq emas
ForEach(data, id: \.self) { item in
    Text(item.title)
}

Custom model standart holatda Hashable emas β€” shuning uchun ForEach-da id: \.self bilan ishlatib bo'lmaydi.


Yechim 1: Identifiable (tavsiya etiladi)

struct MyCustomModel: Identifiable {
    let id: String = UUID().uuidString  // avtomatik noyob ID
    let title: String
}

// Identifiable bo'lganda ForEach id: parametrisiz ishlaydi
ForEach(data) { item in
    Text(item.title)
        .font(.headline)
}

Bu β€” eng oddiy va keng tarqalgan yondashuv. Identifiable qo'shib, id xususiyati berilsa β€” ForEach avtomatik uni noyob identifikator sifatida ishlatadi.


Yechim 2: Hashable (alternativ)

Ba'zan modelga id qo'shish kerak bo'lmaydi yoki boshqa dasturchilar id-ga murojaat qilmasligi kerak. Bu holda Hashable mos keladi:

struct MyCustomModel: Hashable {
    let title: String

    // Hash funksiyasini o'zimiz yozamiz
    func hash(into hasher: inout Hasher) {
        hasher.combine(title)
        // title asosida noyob hash qiymati yaratiladi
    }
}

// Hashable bo'lganda id: \.self ishlatish mumkin
ForEach(data, id: \.self) { item in
    Text(item.title)
        .font(.headline)
}

Bir nechta xususiyatdan hash yaratish

Agar ikkita model bir xil title-ga ega bo'lsa β€” hash qiymatlari ham bir xil bo'ladi, bu muammoga olib kelishi mumkin. Yechim β€” bir nechta xususiyatni birlashtirish:

struct MyCustomModel: Hashable {
    let title: String
    let subtitle: String

    func hash(into hasher: inout Hasher) {
        hasher.combine(title)
        hasher.combine(subtitle)
        // title + subtitle kombinatsiyasi yanada noyob hash beradi
    }
}

Identifiable va Hashable taqqoslov

IdentifiableHashable
Qo'shimcha xususiyatid kerakKerak emas
ForEach yozilishiForEach(data)ForEach(data, id: \.self)
TavsiyaKo'pincha afzalid qo'shmaslik kerak bo'lganda
id-ga tashqaridan murojaatMumkinYo'q

Qachon qaysi?

// Identifiable β€” aksariyat hollarda
// Modelda id bo'lishi tabiiy, tushunish oson
struct ProductModel: Identifiable {
    let id: String = UUID().uuidString
    let name: String
}

// Hashable β€” id kerak emas yoki chiqarilmasligi kerak bo'lganda
struct TagModel: Hashable {
    let name: String
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }
}

Xulosa

ForEach-da id: \.self ko'rganda β€” bu elementning Hashable protokoliga muvofiq kelishidan foydalaniladi. String, Int, Bool kabi standart turlar allaqachon Hashable. Custom struct uchun esa ikki yo'l bor: Identifiable (id qo'shish, tavsiya etiladi) yoki Hashable (hash(into:) funksiyasi yozish). Ko'pchilik holatlarda Identifiable soddaroq va tushunarli, lekin Hashable-ni bilish Swift-da keng uchraydigan kodni tushunishga yordam beradi.

Buy mea coffee