- Published on
SwiftUI advanced: custom binding (Maxsus binding) qanday ishlaydi?
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Binding o'zi nima?
SwiftUI da biz ko'pincha @State o'zgaruvchisiga oldiga $ (dollar) belgisini qo'yib, boshqa view ga berib yuboramiz. Buni Binding deyiladi. Binding orqali bola (child) view ota (parent) view dagi ma'lumotni o'zgartira oladi.
Lekin aslida Binding bu shunchaki ikkita funksiyaning yig'indisi:
- Get (Ma'lumotni olish)
- Set (Yangi ma'lumotni o'rnatish)
Biz hech qanday @State siz ham o'zimizning maxsus Binding'imizni qo'lda yaratishimiz mumkin!
1. Qo'lda Binding yaratish
Aytaylik bizda title nomli oddiy o'zgaruvchi bor va biz uni boshqa view ga Binding orqali o'tkazmoqchimiz.
struct CustomBindingBootcamp: View {
@State private var title: String = "Boshlanish"
var body: some View {
VStack {
Text(title)
// Qo'lda Binding yaratish
let customBinding = Binding(
get: {
return title // Joriy qiymatni qaytaramiz
},
set: { newValue in
title = newValue // Yangi qiymat kelsa, title ni yangilaymiz
}
)
ChildView(title: customBinding)
}
}
}
struct ChildView: View {
@Binding var title: String
var body: some View {
Button("O'zgartirish") {
title = "Yangi sarlavha"
}
}
}
Albatta, haqiqiy kodda biz ChildView(title: $title) deb yozib ketaveramiz, chunki $ belgisi xuddi shu get va set larni avtomatik tayyorlab beradi. Ammo bu logika bizga yanada qiziqroq narsalarni qilish imkonini beradi.
2. Nega bizga Custom Binding kerak? (Muammo)
Deyarli har bir ilovada xatolik (Error) yuz berganda ekranga Alert chiqarishimiz kerak bo'ladi. Odatda biz buni shunday qilamiz:
@State private var errorTitle: String? = nil
@State private var showError: Bool = false
// Alertni chiqarish uchun
Button("Xato yuz berdi") {
errorTitle = "Internet yo'q!"
showError = true // Doim 2 ta o'zgaruvchini tengdaniga o'zgartirish kerak!
}
.alert(errorTitle ?? "Xatolik", isPresented: $showError) {
Button("OK") {}
}
Ko'rib turganingizdek, doim errorTitle ga qiymat berish bilan birga showError = true qilish ham esdan chiqmasligi kerak. Aks holda Alert chiqmay qoladi.
3. Custom Binding bilan yechim
Biz o'zimizga maxsus Binding yozamiz. U @State dagi errorTitle ni tekshiradi: agar u nildan farqli bo'lsa true qaytaradi va alert yopilganda errorTitle ni orqaga nil qilib qo'yadi.
Buning uchun qulay Extension (kengaytma) yozib olamiz:
extension Binding where Value == Bool {
// T - xohlagan tip (String, Int, va hokazo)
init<T>(ifNotNil value: Binding<T?>) {
self.init {
// GET: Agar qiymat nil bo'lmasa, true qaytaramiz
return value.wrappedValue != nil
} set: { newValue in
// SET: Agar Alert yopilib, qiymat false bo'lsa, asli qiymatni nil qilamiz
if newValue == false {
value.wrappedValue = nil
}
}
}
}
Endi SwiftUI kodimiz ajoyib tarzda qisqaradi:
struct CustomBindingBootcamp: View {
// Endi bizga faqat bitta o'zgaruvchi kerak!
@State private var errorTitle: String? = nil
var body: some View {
Button("Xato yuz berdi") {
// Faqat xato matnini beramiz, qolgani avtomatik ishlaydi
errorTitle = "Internet yo'q!"
}
.alert(errorTitle ?? "Xatolik",
isPresented: Binding(ifNotNil: $errorTitle)) { // Maxsus binding'ni ishlatamiz
Button("OK") {}
}
}
}
Xulosa
Custom Binding orqali keraksiz @State Boolean'lardan qutulish, xatolarni kamaytirish va arxitekturani ancha toza qilish mumkin. Swift'dagi Extension larning kuchi aynan shunday vaziyatlarda seziladi!