Published on

Swift'da Generics bilan ishlash asoslari

Authors

Generics o'zi nima?

Tasavvur qiling, sizga ichida info degan o'zgaruvchisi bor model kerak. Birinchi holatda u matn (String), ikkinchi holatda esa mantiqiy qiymat (Bool) bo'lishi lozim.

Tajribasiz dasturchi ikkita alohida struct yaratadi:

struct StringModel {
    let info: String?
}

struct BoolModel {
    let info: Bool?
}

Buning yomon tarafi shundaki, agar ertaga Int yoki Date kerak bo'lib qolsa, yana o'nlab shunday o'xshash structlarni yozib chiqishga to'g'ri keladi. Ularning hammasida info degan joyi bir xil.

Buning eng oson va to'g'ri yo'li — Generic Model yasashdir!

Generic Model yaratish

Generic so'zi "Umumiy" yoki "Universal" degan ma'noni anglatadi. Uni yaratish uchun struct nomidan keyin burchakli qavslar ichiga ixtiyoriy harf (ko'pincha T - Type degan ma'noda) yoziladi.

// T - har qanday ma'lumot turi bo'lishi mumkin!
struct GenericModel<T> {
    let info: T?

    func removeInfo() -> GenericModel {
        return GenericModel(info: nil)
    }
}

Endi biz faqat bitta shu modelning o'zini istalgan turdagi ma'lumotlar bilan bemalol ishlatishimiz mumkin:

class GenericsViewModel: ObservableObject {
    // String bilan ishlaydigan model
    @Published var stringModel = GenericModel(info: "Hello World")

    // Bool bilan ishlaydigan model
    @Published var boolModel = GenericModel(info: true)

    // Int bilan ishlaydigan model
    @Published var intModel = GenericModel(info: 100)
}

Ko'rib turganingizdek biz kodni juda ko'p qisqartirdik va ortiqcha takrorlanishdan saqlanib qoldik. Shuni unutmangki, Swift tilidagi eng mashhur to'plam — Array (Massiv) ham tag-zamirida aynan shunday Generic hisoblanadi. Shuning uchun ham siz .removeAll() funksiyasini hamma turdagi massivlar uchun ishlata olasiz.

Generics ni SwiftUI View'larda ishlatish

Biz Generics ni nafaqat ma'lumotlar (Data), balki View'lar (UI) uchun ham ishlatishimiz mumkin! Masalan siz o'zining ichiga har qanday View ni (Text, Image, tugma va h.k.) qabul qilib oladigan quticha (View) yasamoqchisiz.

import SwiftUI

// T faqat View protokoliga bo'ysunadigan tip bo'lishi shart!
struct GenericView<T: View>: View {
    let title: String
    let content: T

    var body: some View {
        VStack {
            Text(title)
                .font(.largeTitle)

            // Bizga uzatilgan View ni shu yerda chizamiz
            content
        }
    }
}

Bu yerda <T: View> yozuvi shuni anglatadiki, T o'rniga faqatgina SwiftUI ning biron bir elementi kelishi shart. Oddiy String yoki Int yuborish mumkin emas.

Bu shunday ishlatiladi:

struct GenericsBootcamp: View {
    var body: some View {
        // T o'rniga Text yuboryapmiz
        GenericView(title: "Yangi Oyna", content: Text("Custom Content!").foregroundColor(.red))

        // Yoki hatto butun bir Rectangle ham yuborish mumkin
        GenericView(title: "Shakl Oynasi", content: Rectangle().frame(width: 50, height: 50))
    }
}

Yuqoridagi kod View larni parametr sifatida uzatishning ajoyib usulidir. Ammo bundanda zo'rroq, SwiftUI ning haqiqiy sehrli kuchi bor: @ViewBuilder. Keyingi darsda biz xuddi VStack yoki HStack kabi figurali qavslar { } ichiga xohlagancha View larni yozish imkonini beruvchi @ViewBuilder ni o'rganamiz!

Buy mea coffee