Published on

SwiftUI'da Protocol'lar bilan ishlash (Protocols)

Authors

Protokol o'zi nima?

Protokol — bu qoidalar to'plami. Agar biror Klass yoki Struct ushbu protokolga a'zo bo'lsa (conform qilsa), u protokolda aytilgan barcha o'zgaruvchi va funksiyalarni o'zida yozishi shart bo'ladi.

Aslida, siz har kuni protokollardan foydalanasiz. Masalan, har safar yangi ekran yaratganingizda: struct MyView: View { ... } yozasiz. Bu yerdagi View aslida Swift'ning ichki protokoli bo'lib, uning yagona talabi — ichida var body: some View bo'lishi shart!

1. Nega bizga o'zimizning Protokollar kerak?

Aytaylik, ilovamizda Ranglar mavzusi (Color Theme) bor va har bir foydalanuvchi xohlagan rangini tanlashi mumkin:

import SwiftUI

// Default (Asosiy) Ranglar Mavzusi
struct DefaultColorTheme {
    let primary: Color = .blue
    let secondary: Color = .white
    let tertiary: Color = .gray
}

// Boshqa variant
struct AlternativeColorTheme {
    let primary: Color = .red
    let secondary: Color = .black
    let tertiary: Color = .green
}

Endi SwiftUI sahifamizda buni ishlatmoqchimiz:

struct ProtocolsBootcamp: View {
    // Agar biz qatiy qilib DefaultColorTheme ni bersak, uni o'zgartirib bo'lmaydi!
    let colorTheme: DefaultColorTheme = DefaultColorTheme()

    var body: some View {
        ZStack {
            colorTheme.tertiary.ignoresSafeArea()

            Text("Protokollar zo'r!")
                .foregroundColor(colorTheme.secondary)
                .padding()
                .background(colorTheme.primary)
                .cornerRadius(10)
        }
    }
}

Muammo shundaki, biz o'zgaruvchining turini (type) aynan DefaultColorTheme deb berdik. Agar AlternativeColorTheme ga o'zgartirmoqchi bo'lsak, xatolik beradi. Chunki ular ikkita butunlay boshqa-boshqa Struct'lar! Swift ularning ikkalasi ham rang ekanligini bilmaydi.

2. Yechim: Protokol yaratamiz

Ushbu muammoni hal qilish uchun umumiy bir qoida (Protokol) yozamiz:

protocol ColorThemeProtocol {
    var primary: Color { get }
    var secondary: Color { get }
    var tertiary: Color { get }
}

Eslatma: Protokollarda let ishlata olmaymiz. Uning o'rniga var yozamiz va oxiriga o'qish uchun { get } yoki o'zgartirish ham mumkin bo'lsa { get set } yozib qo'yamiz.

Endi ranglar mavzumizni ushbu protokolga bo'ysundiramiz:

struct DefaultColorTheme: ColorThemeProtocol {
    let primary: Color = .blue
    let secondary: Color = .white
    let tertiary: Color = .gray
}

struct AlternativeColorTheme: ColorThemeProtocol {
    let primary: Color = .red
    let secondary: Color = .black
    let tertiary: Color = .green
}

3. Protokolni View ichida ishlatish

Endi biz View ichidagi colorTheme ni bemalol o'zgartira olamiz. Chunki biz uning turi ColorThemeProtocol deymiz. Ya'ni u shartlarga javob beradigan ixtiyoriy Struct bo'lishi mumkin:

struct ProtocolsBootcamp: View {
    // Diqqat! Turi Protocol nomi qilib belgilandi
    let colorTheme: ColorThemeProtocol

    var body: some View {
        ZStack {
            colorTheme.tertiary.ignoresSafeArea()

            Text("Protokollar orqali almashinuv!")
                .foregroundColor(colorTheme.secondary)
                .padding()
                .background(colorTheme.primary)
                .cornerRadius(10)
        }
    }
}

// Ishlatish jarayonida xohlagan mavzuni berib yuborish mumkin:
struct ProtocolsBootcamp_Previews: PreviewProvider {
    static var previews: some View {
        ProtocolsBootcamp(colorTheme: AlternativeColorTheme())
        // yoki
        // ProtocolsBootcamp(colorTheme: DefaultColorTheme())
    }
}

4. Boshqa imkoniyatlari

Protokollar nafaqat o'zgaruvchilarni, balki funksiyalarni ham talab qilishi mumkin. Shuningdek, bitta protokol boshqa protokollarni o'z ichiga olishi mumkin (Protokollar merosxo'rligi):

protocol ButtonTextProtocol {
    var buttonText: String { get }
}

protocol ButtonPressedProtocol {
    func buttonPressed()
}

// Ikkala qoidani o'zida jamlagan super-protokol
protocol ButtonDataSourceProtocol: ButtonTextProtocol, ButtonPressedProtocol {
    // Qolgan qo'shimcha talablar...
}

Xulosa: Protokollar katta ilovalar (Dependency Injection, Testing) yaratishda eng kerakli vosita hisoblanadi. Ular yordamida har xil sinflarni (Classes / Structs) osongina bir-birining o'rniga almashtirib ishlatish mumkin.

Buy mea coffee