- Published on
Task va .task modifier'dan foydalanish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Task nima o'zi?
Biz oldingi maqolalarda async funksiyalarni ishlatib kelyapmiz. Ammo, oddiy (sinxron) kodimizdan turib (masalan SwiftUI dagi .onAppear blokida) async funksiyani to'g'ridan-to'g'ri chaqira olmaymiz. Dasturni asinxron muhitga olib kirish uchun biz Task (vazifa) yaratishimiz kerak.
Ushbu darsda biz Task'larning turlari, ularning ustuvorligi (priority), shuningdek, ularni qanday qilib o'rta yo'lda to'xtatish (cancel) va yield qilishni ko'rib chiqamiz.
Task ustuvorliklari (Priorities)
Bir vaqtning o'zida ilovamizda yuzlab Task'lar ishlashi mumkin. Qaysi biri muhimroq va qaysi biri birinchi bajarilishi kerak? Buning uchun har bir Task'ga ustuvorlik (priority) berishimiz mumkin.
Ustuvorlik darajalari yuqoridan pastga (eng muhimidan eng sekinigacha) quyidagilardir:
// 1. Eng yuqori darajalar
Task(priority: .userInitiated) {
print("User Initiated: Foydalanuvchi bevosita kutayotgan operatsiyalar")
}
Task(priority: .high) {
print("High: Juda muhim va tezkor vazifalar")
}
// 2. O'rta daraja
Task(priority: .medium) {
print("Medium: Oddiy operatsiyalar")
}
// 3. Pastki darajalar
Task(priority: .low) {
print("Low: Shoshilinch bo'lmagan amallar")
}
Task(priority: .utility) {
print("Utility: Orqa fondagi ishlar, masalan, fayllarni keshga yozish")
}
Task(priority: .background) {
print("Background: Eng past ustuvorlik (masalan loglarni jo'natish)")
}
Eslatma: Ustuvorlikni berish – bu albatta o'sha Task boshqalaridan oldin tugaydi degani emas. Tizim ularni eng optimal tarzda rejalashtiradi va imkon qadar yuqori ustuvorlikdagilarga ko'proq resurs ajratadi.
Task.yield() orqali yo'l berish
Ba'zida biz juda katta va uzoq davom etadigan Task yozamiz. Agar bu Task resurslarni band qilib tursa, boshqa muhim ishlarga xalaqit berishi mumkin. Bunday paytda tizimga "men hozir biroz to'xtab turishga va boshqa navbat kutayotgan Tasklarga yo'l berishga tayyorman" deyish imkoniyati mavjud. Bu Task.yield() deyiladi.
Task(priority: .high) {
// ... qandaydir og'ir ishlar ...
// Tizimga boshqa amallarni bajarish uchun o'z o'rnimizni (oz muddatga) bo'shatamiz
await Task.yield()
// ... ishda davom etamiz ...
}
Child (Bola) Task'lar vs Detached (Ajralgan) Task'lar
Task ichida turib yana yangi Task ochishimiz mumkin. Bunday holatda ichki Task o'z otasi bo'lgan (tashqi) Task'ning xususiyatlarini (jumladan priority'sini) avtomatik o'ziga meros qilib oladi.
Task(priority: .userInitiated) {
// 1. Bola Task: Otasidan .userInitiated prioritetini meros oladi
Task {
print("Child task ishlamoqda")
}
// 2. Detached Task: Ota taskdan butkul alohida va hech narsani meros olmagan Task.
// Apple hujjatlarida buni iloji boricha ISHLATMASLIK tavsiya etiladi.
Task.detached {
print("Detached task ishlamoqda")
}
}
Tasklarni to'xtatish (Cancel)
Asinxron operatsiyalar vaqt oladi. Agar foydalanuvchi ma'lumot yuklanayotgan ekrandan (View'dan) boshqa ekranga o'tib ketsa, eski ekrandagi yuklash (Task) baribir orqa fonda ishlab turadi! Bu xotira va internetni isrof qiladi. Bunga yo'l qo'ymaslik uchun ekran yopilganda Taskni cancel (bekor) qilishimiz kerak.
struct TaskBootcamp: View {
// Task'ni ushlab turish uchun o'zgaruvchi
@State private var fetchImageTask: Task<Void, Never>? = nil
var body: some View {
VStack {
// view elementlari
}
.onAppear {
// Ekranga kirganda Taskni boshlaymiz va uni o'zgaruvchiga saqlaymiz
fetchImageTask = Task {
await viewModel.fetchImage()
}
}
.onDisappear {
// Ekrandan chiqqanda Taskni to'xtatamiz
fetchImageTask?.cancel()
}
}
}
Haqiqiy Sehr: .task Modifier'i
Yuqoridagi (onAppear + saqlash + onDisappear/cancel) mantiqi shu qadar ko'p ishlatiladiki, Apple iOS 15 dan boshlab bularning hammasini o'z ichiga oladigan bitta universal modifier taqdim qildi. Bu .task modifikatoridir!
struct TaskBootcamp: View {
var body: some View {
VStack {
// view elementlari
}
// .task quyidagilarni avtomatik qiladi:
// 1. onAppear bo'lganda asinxron muhit (Task) ochib beradi.
// 2. onDisappear bo'lganda, ichidagi hamma narsani avtomatik CANCEL qiladi!
.task {
await viewModel.fetchImage()
}
}
}
Ko'rib turganingizdek, SwiftUI'dagi .task modifikatori asinxron ishlar uchun hayotimizni juda osonlashtiradi va qator kodlarni qisqartiradi. Kelajakda deyarli barcha kodlarimizda biz aynan shundan foydalanamiz!