- Published on
SwiftUI'da .refreshable (Pull to Refresh)
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Pull to Refresh nima?
Deyarli barcha iOS ilovalarda (masalan, Telegram, Instagram yoki Mail) ro'yxatni (List/ScrollView) tepadan pastga tortsangiz aylanuvchi doira (Spinner) chiqadi va yangi ma'lumotlar yuklanadi. Oldinlari buni SwiftUI'da noldan yozish juda qiyin edi. Hozir esa buning uchun ro'yxatga shunchaki .refreshable modifierini tirkab qo'yish kifoya.
Bu modifier aynan Swift Concurrency (Async Await) bilan birga ishlash uchun maxsus yaratilgan!
Async Await'siz ishlatsa nima bo'ladi?
Deylik bizda MVVM arxitekturasida yozilgan odatiy sinxron funksiya bor.
class MyViewModel: ObservableObject {
@Published var items: [String] = []
// Bu funksiya sinxron, uning o'zi asinxron emas!
func loadDataSync() {
Task {
// Ma'lumotni yuklash 5 soniya vaqt oladi
let newItems = await fetchDataFromServer()
self.items = newItems
}
}
}
Endi keling ushbu funksiyani .refreshable modifieriga beramiz:
ScrollView {
// ...
}
.refreshable {
// Foydalanuvchi ekranni tortganda shu funksiya ishlaydi
vm.loadDataSync()
}
Natija nima bo'ladi? Foydalanuvchi ekranni tortadi, aylanuvchi doira (Spinner) paydo bo'ladi... va darhol yo'qoladi! Lekin ma'lumotlar aslida 5 soniyadan keyin keladi. Nima uchun bunday bo'ldi? Chunki .refreshable modifieri biz bergan loadDataSync() funksiyasini chaqirdi va funksiya darhol tugadi (ichidagi Task esa fonda ishlashni davom ettirdi). Funksiya tugaganligi uchun Spinner ham o'chib qoldi.
To'g'ri va Mukammal usul (Async funksiya bilan)
Ushbu muammoni hal qilishning yakkayu-yagona to'g'ri usuli – ViewModel'dagi ma'lumotlarni yangilash funksiyasini to'g'ridan-to'g'ri async qilishdir!
@MainActor
class MyViewModel: ObservableObject {
@Published var items: [String] = []
// Endi funksiyamiz to'g'ridan-to'g'ri async qilib belgilandi!
func loadDataAsync() async {
// Ma'lumotni yuklash 5 soniya vaqt oladi
let newItems = await fetchDataFromServer()
self.items = newItems
}
}
Endi Ekranda (View'da) buni chaqiramiz:
ScrollView {
// ...
}
.refreshable {
// 💡 Await so'zi orqali biz Spinner'ga "Kutib turgin!" deyapmiz
await vm.loadDataAsync()
}
Endi Natija qanday? Foydalanuvchi ekranni tortadi. Spinner paydo bo'ladi. U loadDataAsync() tugashini (5 soniya) await (kutadi). Ma'lumot to'liq kelib o'zgaruvchilarga saqlangach, funksiya o'z ishini yakunlaydi va shundan keyingina Spinner yo'qoladi!
TIP
Qoida: Hech qachon .refreshable ichida Task { } ochib o'tirmang! Buning o'rniga chaqirilayotgan funksiyaning o'zini async qiling va .refreshable ichida uni to'g'ridan-to'g'ri await qilib chaqiring.
Xulosa
SwiftUI va Swift Concurrency bir-biri uchun maxsus yaratilgan go'zal juftlikdir. Agar siz .refreshable kabi zo'r va tayyor xususiyatlardan maksimal darajada (Xuddi haqiqiy iOS app'laridagidek) foydalanmoqchi bo'lsangiz, albatta uni Asinxron funksiyalar yordamida qo'llashingiz zarur. Bitta await so'zi butun UI tajribasini (User Experience) tubdan yaxshilab yuborishiga o'zingiz guvoh bo'ldingiz!