Property Wrapper — bu Swift mexanizmi bo'lib, kodni takrorlamasdan xususiyatlarga kirish va o'zgartirish uchun mantiq qatlamini qo'shadi. SwiftUI da Property Wrappers ko'rinishlar holatini boshqarishning asosiga aylandi: @State, @Binding, @ObservedObject, @StateObject va @Environment. Swift hujjatlariga (2025) ko'ra, xususiyat o'ramlari loyihalarda shablon kodini o'rtacha 40% ga kamaytiradi. Property Wrapper ni tushunish har bir iOS dasturchisi uchun framework bilan samarali ishlash uchun zarurdir.
Asosiy fikrlar
Property Wrapper — Swift 5.1 versiyasida paydo bo'lgan til konstruksiyasi bo'lib, xususiyatga kirish mantiqini alohida turga inkapsulyatsiya qilish imkonini beradi. Har bir sinfda takrorlanuvchi getter va setterlarni yozish o'rniga, dasturchi o'ramni bir marta e'lon qiladi va uni @ turidan oldin annotatsiya orqali qo'llaydi. Swift avtomatik ravishda xususiyatni ko'rsatilgan turga o'raydi, o'qish va yozish paytida uning wrappedValue va projectedValue metodlarini chaqiradi. Apple ga ko'ra (WWDC 2019), Property Wrappers SwiftUI uchun asosiy abstraksiyaga aylandi.
Xususiyat o'rami @propertyWrapper atributiga ega bo'lgan struktura yoki sinfdir. Ichkarida bunday tur joriy qiymatni qaytaradigan va o'rnatadigan wrappedValue xususiyatini amalga oshirishi kerak. Swift kompilyatori asl xususiyatga murojaatlarni wrappedValue chaqiruvlari bilan almashtiradi, amalga oshirishni chaqiruvchi koddan butunlay yashiradi. Qo'shimcha ravishda projectedValue — $ belgisi orqali mavjud bo'lgan proyeksiya aniqlanishi mumkin.
Property Wrappers ning afzalligi mantiqni qayta ishlatishdadir. Masalan, email validatsiyasi, qiymatlarni keshlash yoki saqlash bilan sinxronlash uchun o'ram yaratish mumkin — va uni loyihadagi istalgan xususiyatga qo'llash mumkin. SwiftUI da bu kontseptsiya hamma joyda qo'llaniladi: holatni boshqarishning har bir mexanizmi alohida Property Wrapper sifatida amalga oshirilgan.
@WrapperType var value: T annotatsiyasi bilan xususiyat e'lon qilinganda, Swift kompilyatori kodni o'zgartiradi. U WrapperType ning namunasini yaratadi va xususiyatga kirishni wrappedValue orqali generatsiya qiladi. Manba kodi let x = value, let x = _value.wrappedValue ga, value = newValue esa _value.wrappedValue = newValue ga aylanadi. Bu o'zgartirish kompilyatsiya bosqichida, runtime yuklamasiz sodir bo'ladi.
@propertyWrapper
struct Capitalized {
private var text: String
var wrappedValue: String {
get { text }
set { text = newValue.capitalized }
}
init(initialValue: String) {
text = initialValue.capitalized
}
}
Listingda Capitalized o'rami ko'rsatilgan bo'lib, u matnni avtomatik ravishda bosh harf bilan formatlaydi. Qiymat belgilanganda setter saqlashdan oldin capitalized ni chaqiradi. Endi @Capitalized annotatsiyasiga ega bo'lgan har qanday xususiyat faqat to'g'ri formatlangan matnni saqlaydi. Bu yondashuv validatsiya va formatlash kodining takrorlanishini butunlay yo'q qiladi.
Proyeksiya (projectedValue) — $ prefiksi orqali mavjud bo'lgan qo'shimcha aloqa kanalidir. SwiftUI da bu imkoniyat hamma joyda qo'llaniladi: $state Binding
SwiftUI holatni boshqarish uchun beshta o'rnatilgan Property Wrapper ni o'z ichiga oladi: @State, @Binding, @ObservedObject, @StateObject va @Environment. Ularning har biri muayyan vazifani hal qiladi va turli stsenariylarda qo'llaniladi. @State oddiy mahalliy ma'lumotlar uchun, @Binding — ma'lumotlar havolasini bolaviy ko'rinishlarga uzatish uchun, @ObservedObject va @StateObject — murakkab ob'ektlar uchun, @Environment — iyerarxiyadagi tizim qiymatlari uchun mo'ljallangan.
| Wrapper | Vazifasi | Egalik |
|---|---|---|
| @State | Bitta ko'rinishning mahalliy holati | Joriy ko'rinish |
| @Binding | Ota-ona bilan ikki tomonlama bog'lanish | Ota-ona ko'rinish |
| @ObservedObject | Tashqi ob'ektni kuzatish | Tashqi egasi |
| @StateObject | ObservableObject yaratish | Joriy ko'rinish |
| @Environment | Iyerarxiyadan tizim qiymatlari | SwiftUI muhiti |
Muayyan Property Wrapper ni tanlash ma'lumot manbai va ularning hayotiy tsikliga bog'liq. Agar ma'lumotlar bitta ko'rinishga tegishli bo'lsa va bolaviy komponentlarga kerak bo'lmasa — @State dan foydalaning. Agar bolaviy ko'rinish ota-onaning ma'lumotlarini o'zgartirishi kerak bo'lsa — @Binding ni qo'llang. Bir nechta ko'rinishlarda ishlatiladigan ob'ektlar uchun @ObservedObject va @StateObject mos keladi.
@State — bu bitta ko'rinish ichida mahalliy holatni saqlash uchun Property Wrapper. SwiftUI @State xususiyatlari uchun xotirani avtomatik boshqaradi va har bir o'zgarishda ko'rinishni qayta chizadi. @State faqat joriy ko'rinishga tegishli bo'lgan oddiy turlar (String, Int, Bool, enum) va strukturalar uchun mos keladi. Qiymat o'zgarganda, SwiftUI body xususiyatini qayta ishga tushiradi.
struct CounterView: View {
@State private var count: Int = 0
var body: some View {
VStack {
Text("Sanoq: \(count)")
Button("Oshirish") {
count += 1
}
}
}
}
Misolda, @State xususiyati count hisoblagichning joriy qiymatini saqlaydi. SwiftUI bu xususiyat uchun xotira maydonini heap da yaratadi va uni CounterView ning hayotiy tsikli bilan bog'laydi. Tugma bosilganda count 1 ga oshadi, SwiftUI o'zgarishni aniqlaydi va body ni qayta ishga tushirib, yangi qiymatni ko'rsatadi. Muhim: @State murakkab havola turlari uchun ishlatilmasligi kerak — buning uchun @StateObject va @ObservedObject mo'ljallangan.
@Binding boshqa ko'rinishga tegishli bo'lgan ma'lumot manbaiga havola yaratadi. Binding qiymatni mustaqil saqlamaydi — u @State, @StateObject yoki otadan uzatilgan boshqa Binding orqali ma'lumotlarni o'qiydi va yozadi. Bu bolaviy komponentlarga ma'lumotlarga to'g'ridan-to'g'ri egalik qilmasdan va callback larsiz ajdodning holatini o'zgartirish imkonini beradi.
struct ToggleSwitch: View {
@Binding var isOn: Bool
var body: some View {
Toggle("Switch", isOn: $isOn)
}
}
Listingda ToggleSwitch ota-ona ko'rinishdan @BindingBool oladi. Ota-ona @State var isToggleOn = false yaratadi va $isToggleOn ni ToggleSwitch ning inizializatoriga uzatadi. Foydalanuvchi bolaviy ko'rinish ichida Toggle ni o'zgartirganda, o'zgarish darhol ota-onaning @State ida aks etadi. Binding mexanizmi iyerarxiyada yuqoriga o'zgarishlarni uzatish uchun delegatlar yoki closure larga bo'lgan ehtiyojni butunlay yo'q qiladi.
@ObservedObject — bu tashqaridan uzatilgan ObservableObject namunasini kuzatish uchun Property Wrapper. Ko'rinish bu ob'ektning egasi emas — u ota-ona komponentida yaratiladi yoki Environment orqali in'ektsiya qilinadi. ObservableObject ichidagi har qanday @Published xususiyati o'zgarganda, SwiftUI @ObservedObject orqali obuna bo'lgan barcha ko'rinishlarni qayta chizadi.
@StateObject — bu to'g'ridan-to'g'ri ko'rinishda ObservableObject yaratish va unga egalik qilish uchun o'ram. @ObservedObject dan farqli o'laroq, @StateObject ob'ektning ko'rinishning butun hayotiy tsikli davomida yagona namunasi bo'lishini kafolatlaydi. SwiftUI ko'rinish strukturasini qayta yaratgan taqdirda ham (tez-tez sodir bo'ladi), @StateObject mavjud ob'ektni saqlab qoladi va inizializatorni qayta chaqirmaydi.
class UserSettings: ObservableObject {
@Published var username: String = "Guest"
}
struct ProfileView: View {
@StateObject var settings = UserSettings()
var body: some View {
ChildProfileView(settings: settings)
}
}
struct ChildProfileView: View {
@ObservedObject var settings: UserSettings
var body: some View {
Text("Salom, \(settings.username)")
}
}
Misolda ProfileView @StateObject orqali UserSettings yaratadi, ob'ektning egasiga aylanadi. ChildProfileView xuddi shu namunani @ObservedObject orqali oladi — kuzatadi, lekin hayotiy tsiklni boshqarmaydi. username o'zgarganda ikkala ko'rinish ham yangilanadi. Agar ChildProfileView @ObservedObject o'rniga @StateObject dan foydalanganda, har bir renderda boshlang'ich qiymat bilan yangi namuna yaratilgan bo'lar edi.
Asosiy qoida: @StateObject ob'ektni yaratadigan ko'rinishda (haqiqat manbai), @ObservedObject esa tayyor ob'ektni otadan oladigan ko'rinishda qo'llaniladi. Bu qoidaning buzilishi holatning yo'qolishiga yoki ma'lumotlarning kutilmagan qayta yaratilishiga olib keladi.
Swift har qanday takrorlanuvchi xususiyatga kirish mantig'i uchun shaxsiy Property Wrappers yaratish imkonini beradi. @propertyWrapper atributiga ega struktura yoki sinfni e'lon qilish va wrappedValue ni amalga oshirish kifoya. Quyida UserDefaultsWrapper o'rami ko'rsatilgan bo'lib, u qiymatni avtomatik ravishda UserDefaults bilan sinxronlashtiradi.
@propertyWrapper
struct UserDefaultsWrapper<T> {
let key: String
let defaultValue: T
var wrappedValue: T {
get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue }
set { UserDefaults.standard.set(newValue, forKey: key) }
}
}
struct AppConfig {
@UserDefaultsWrapper(key: "theme", defaultValue: "light")
var theme: String
}
UserDefaultsWrapper o'rami UserDefaults tomonidan qo'llab-quvvatlanadigan har qanday ma'lumot turi bilan ishlash uchun generic T dan foydalanadi. Getter qiymatni kalit bo'yicha o'qiydi, setter yozadi. @UserDefaultsWrapper(key:defaultValue:) ni theme xususiyatiga qo'llash uni avtomatik ravishda saqlash bilan bog'laydi — UserDefaults bilan ishlashning barcha mantig'i o'ram ichida yashiringan. Bu Property Wrappers yordamida shablon kodini kamaytirishning odatiy namunasidir.
Shaxsiy o'ramlarni yaratishda ishlash ni hisobga olish muhimdir. Getter va setter xususiyatga har bir kirishda chaqirilganligi sababli, wrappedValue ga og'ir I/O operatsiyalarini joylashtirmaslik kerak. Asinxron ma'lumotlarni saqlash uchun Property Wrappers ni ObservableObject va @Published bilan birlashtirish yaxshiroqdir.
Tez-tez beriladigan savollar
@State oddiy turlar (String, Int, Bool) va strukturalar uchun mo'ljallangan, @StateObject esa ObservableObject ni amalga oshiradigan havola turlari uchun. @State qiymatni to'g'ridan-to'g'ri SwiftUI da saqlaydi, @StateObject sinf namunasini heap da boshqaradi.
Ha, @Binding @StateObject, @ObservedObject yoki boshqa Binding dan $ proyeksiyasi yordamida yaratilishi mumkin. Shuningdek, Binding ObservableObject dan $object.$publishedProperty orqali yoki InlineBinding dan Binding.constant(value) orqali initsializatsiya qilinadi.
Global ma'lumotlar uchun @EnvironmentObject dan foydalaning yoki ObservableObject ni EnvironmentValues orqali in'ektsiya qiling. @StateObject keyinchalik @ObservedObject orqali bolaviy komponentlarga uzatish bilan ildiz ko'rinish uchun mos keladi.
@ObservedObject ob'ektga ega emas — agar ota-ona ko'rinish qayta yaratilsa va yangi namunani uzatsa, @ObservedObject unga o'tadi. Holatni yo'qotmaslik uchun egalik qiluvchi ko'rinish @StateObject dan foydalanishi kerak.
Ha, lekin sinf ichida @Published va async funksiyalari bilan ObservableObject kombinatsiyasidan foydalanish osonroq. Property Wrapper tabiatan sinxrondir — wrappedValue har bir kirishda hisoblanadi, bu uzoq muddatli operatsiyalar uchun mos emas.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.
Shuningdek o'qing