- Published on
Swiftda property wrappers
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Property Wrapper — property ga "xulq-atvor" qo'shish usuli. SwiftUIda har kuni ishlatiladigan @State, @Published, @AppStorage, @Binding — bularning hammasi property wrapper. O'zingiz ham yaratishingiz mumkin — qiymatni cheklash, tekshirish, avtomatik saqlash kabi logikalarni bitta joyda yozib, ko'p property larda qayta ishlatish.
Property Wrapper ning asosiy tushunchalari: wrappedValue — foydalanuvchi ko'radigan va o'zgartiradigan asosiy qiymat. projectedValue ($ prefiksi bilan) — qo'shimcha ma'lumot (masalan, @State da $name Binding qaytaradi).
Property Wrapper yaratish
@propertyWrapper atributi struct yoki class ni property wrapper sifatida belgilaydi. wrappedValue property majburiy. Quyida qiymatni belgilangan oraliqda cheklaydigan wrapper ko'rsatilgan.
// ═══════════════════════════════════════
// @PROPERTYWRAPPER — o'z wrapper imizni yaratamiz
// Bu wrapper qiymatni 0...100 oraliqda cheklaydi
// ═══════════════════════════════════════
@propertyWrapper
struct Chegaralangan {
private var qiymat: Int
private let min: Int
private let max: Int
// wrappedValue — asosiy qiymat (tashqaridan ko'rinadigan)
var wrappedValue: Int {
get { qiymat }
set { qiymat = Swift.min(Swift.max(newValue, min), max) }
// newValue min dan kichik bo'lsa min, max dan katta bo'lsa max
}
init(wrappedValue: Int, min: Int, max: Int) {
self.min = min
self.max = max
// Init da ham cheklash
self.qiymat = Swift.min(Swift.max(wrappedValue, min), max)
}
}
// Ishlatish — @ bilan
struct OyinBotirma {
@Chegaralangan(min: 0, max: 100) var hayot = 100
@Chegaralangan(min: 0, max: 10) var daraja = 1
}
var botir = OyinBotirma()
botir.hayot = 150 // 100 ga chegaralanadi (max)
print(botir.hayot) // 100
botir.hayot = -20 // 0 ga chegaralanadi (min)
print(botir.hayot) // 0
botir.daraja = 15 // 10 ga chegaralanadi
print(botir.daraja) // 10
projectedValue — $ bilan qo'shimcha ma'lumot
projectedValue — $ prefiksi bilan chaqiriladigan qo'shimcha qiymat. Masalan, @State var ism = "" da $ism Binding<String> qaytaradi. O'z wrapper ingizda projectedValue ni qo'shib, qo'shimcha ma'lumot berish mumkin.
// ═══════════════════════════════════════
// PROJECTEDVALUE — $ prefiksi bilan chaqiriladigan qo'shimcha qiymat
// ═══════════════════════════════════════
@propertyWrapper
struct BoshHarfli {
private var matn: String
var wrappedValue: String {
get { matn }
set { matn = newValue.capitalized }
// .capitalized — har so'zning bosh harfi katta
}
// $ bilan chaqiriladi — asl qiymatni ko'rsatadi
var projectedValue: String {
matn.uppercased() // HAMMASI KATTA HARF
}
init(wrappedValue: String) {
self.matn = wrappedValue.capitalized
}
}
struct Profil {
@BoshHarfli var ism = "ali valiyev"
}
var profil = Profil()
print(profil.ism) // "Ali Valiyev" (wrappedValue)
print(profil.$ism) // "ALI VALIYEV" (projectedValue)
// SwiftUIda $state — Binding qaytaradi
// @State var ism = "" → $ism = Binding<String>
@State va @Published qanday ishlaydi
SwiftUIning @State va Combine ning @Published aslida property wrapper. @State qiymat o'zgarganda View ni qayta chizadi. @Published qiymat o'zgarganda ObservableObject orqali barcha kuzatuvchilarga signal yuboradi. Quyida ularning soddalashtirilgan ishlash tartibi ko'rsatilgan.
// ═══════════════════════════════════════
// @STATE — soddalashtirilgan ko'rinish
// (Apple ning haqiqiy implementatsiyasi murakkab)
// ═══════════════════════════════════════
// @State aslida shunday ishlaydi:
// 1. wrappedValue — qiymatni o'qish/yozish
// 2. projectedValue ($) — Binding qaytaradi
// 3. Qiymat o'zgarganda — SwiftUI View ni qayta chizadi
// ═══════════════════════════════════════
// @PUBLISHED — soddalashtirilgan ko'rinish
// ═══════════════════════════════════════
// @Published aslida shunday ishlaydi:
// 1. wrappedValue — qiymatni o'qish/yozish
// 2. projectedValue ($) — Combine Publisher qaytaradi
// 3. willSet da — ObservableObject.objectWillChange signal yuboradi
// Misol: @Published ni tushunish
import Combine
@propertyWrapper
struct XabardorQiymat<T> {
private var qiymat: T
// Publisher — qiymat o'zgarganda signal
let publisher = PassthroughSubject<T, Never>()
var wrappedValue: T {
get { qiymat }
set {
qiymat = newValue
publisher.send(newValue) // Kuzatuvchilarga xabar
}
}
var projectedValue: PassthroughSubject<T, Never> {
publisher
}
init(wrappedValue: T) {
self.qiymat = wrappedValue
}
}
Amaliy misollar
Property Wrapper ning chinakam kuchi amaliy misollarda namoyon bo'ladi. @UserDefaultsda — qiymatni avtomatik UserDefaults ga saqlash. @Tozalangan — matn atrofidagi bo'shliqlarni avtomatik olib tashlash. Bir marta yozib, ko'p joyda ishlatish mumkin.
// ═══════════════════════════════════════
// @USERSDEFAULTS — avtomatik saqlash
// ═══════════════════════════════════════
@propertyWrapper
struct UserDefaultsda<T> {
let kalit: String
let boshlangich: T
var wrappedValue: T {
get { UserDefaults.standard.object(forKey: kalit) as? T ?? boshlangich }
set { UserDefaults.standard.set(newValue, forKey: kalit) }
}
}
struct Sozlamalar {
@UserDefaultsda(kalit: "qorong'uRejim", boshlangich: false)
var qorong'uRejim: Bool
@UserDefaultsda(kalit: "tilKodi", boshlangich: "uz")
var til: String
}
var soz = Sozlamalar()
soz.qorong'uRejim = true // UserDefaults ga avtomatik saqlandi
// ═══════════════════════════════════════
// @TRIMMED — bo'shliqlarni olib tashlash
// ═══════════════════════════════════════
@propertyWrapper
struct Tozalangan {
private var matn: String = ""
var wrappedValue: String {
get { matn }
set { matn = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
}
init(wrappedValue: String) {
self.wrappedValue = wrappedValue
}
}
struct RoyxatdanOtish {
@Tozalangan var email = ""
@Tozalangan var ism = ""
}
var forma = RoyxatdanOtish()
forma.email = " ali@mail.com "
print(forma.email) // "ali@mail.com" — bo'shliqlar olib tashlandi
🎯 Topshiriq
@Parolga property wrapper yarating: kamida 8 ta belgi, kamida 1 ta raqam bo'lishi kerak. Agar qoida buzilsa — eski qiymatni saqlang. projectedValue sifatida Bool (parol kuchli/kuchsiz) qaytaring. $parol bilan tekshiring.