@MainActor Swift tilidagi global aktyor bo'lib, kodning asosiy oqimda bajarilishini kafolatlaydi. Apple Developer, 2024 ma'lumotlariga ko'ra, @MainActor UI bilan ishlashda asosiy oqimga o'tishni avtomatlashtiradi va dasturchini DispatchQueue.main.async qo'lda chaqirishdan ozod qiladi. Annotatsiya Swift 5.5 da async/await tizimi bilan birga paydo bo'ldi.
Asosiy fikrlar
@MainActor Swift-da global aktyor (global actor) bo'lib, aktyorlarning xususiyatlarini ilovaning asosiy oqimida bajarilish kafolati bilan birlashtiradi. U Swift 5.5 da async/await va strukturali parallellik bilan birga taqdim etilgan Swift parallellik tizimining bir qismidir. Annotatsiya dasturchiga oqimlarni qo'lda almashtirish haqida o'ylamaslikka imkon beradi va UI xatolar sonini kamaytiradi.
Swift-dagi aktyor — bu o'z holatini izolyatsiya qiladigan va faqat bitta oqim uni o'zgartirishi mumkinligini kafolatlaydigan referens turidir. @MainActor — bu ijrochisi asosiy oqim bo'lgan maxsus global aktyor. @MainActor bilan belgilangan har qanday kod asosiy oqimda bajariladi — hatto fon vazifasidan chaqirilgan bo'lsa ham.
@MainActor paydo bo'lishidan oldin, dasturchilar DispatchQueue.main.async orqali qo'lda asosiy oqimga o'tishardi. Bu tez-tez xatolarga sabab bo'lardi: dasturchilar o'tishni unutib, UI-ni asosiy bo'lmagan oqimda yangilab, ishdan chiqishlarga olib kelishardi. @MainActor bu muammoni tur tizimi darajasida hal qiladi.
iOS ilovalaridagi ko'pchilik xatolarning manbai UI-xavfsizlik — interfeysni fon oqimidan yangilashdir. Apple @MainActor-ni Swift Concurrency-ga kiritdi, shunda asosiy oqimga o'tish avtomatik va kompilyator tomonidan tekshiriladigan bo'lsin va butun bir runtime xatolar sinfini yo'q qilsin.
Ishlash printsipi Swift Concurrency ijro tizimiga asoslangan. Oqim @MainActor bilan belgilangan funksiyani chaqirganda, rejalashtiruvchi uni joriy ijrochida to'xtatadi va asosiy oqimda qayta boshlaydi. Kompilyator chaqiruv chegaralarini kuzatadi va xavfsizlikni kafolatlaydi.
@MainActor bajarilishi uchun MainActor.shared javobgardir — ilovaning asosiy oqimi bilan bog'liq ijrochi. Asinxron funksiya @MainActor bilan belgilanganda, u har doim shu ijrochida qayta boshlanadi, asl vazifa qaysi oqimda boshlanganidan qat'iy nazar.
import SwiftUI
class ViewModel: ObservableObject {
@Published var items: [String] = []
@MainActor
func loadData() async {
let result = await fetchRemoteData()
items = result // xavfsiz, MainActor asosiy oqimni kafolatlaydi
}
}
Agar funksiya @MainActor bilan belgilangan va boshqa asinxron funksiyani chaqirsa, u sukut bo'yicha aktor kontekstini meros qilib oladi. Bu shuni anglatadiki, barcha ichki chaqiruvlar ham asosiy oqimda bajariladi, agar boshqacha ko'rsatilmagan bo'lsa. Kompilyator buni kuzatadi va mos kelmaydigan closure uzatishga urinishda xato beradi.
@MainActor va DispatchQueue.main solishtiruvi yangi mexanizm nima uchun xavfsizroq va qulayroq deb hisoblanishini tushunishga yordam beradi, garchi ikkalasi ham bir vazifani — kodni asosiy oqimda bajarishni — hal qilsa.
@MainActor — bu kompilyator darajasida tekshirish. @MainActor funksiyasini xavfsiz bo'lmagan kontekstdan chaqirishga urinsangiz, kompilyator ogohlantirish yoki xato beradi. DispatchQueue.main.async — bu runtime chaqiruvi: kod kompilyatsiya qilinadi, lekin UI-ni fon oqimidan yangilashga urinishda runtime-da ishdan chiqishi mumkin.
DispatchQueue.main.async navbatga kechikish bilan bajarilishi mumkin bo'lgan blok qo'shadi. @MainActor async/await bilan ortiqcha closurelar yaratmasdan to'g'ridan-to'g'ri ijrochi almashtirishni amalga oshiradi. Bu yukni kamaytiradi va kodni bajarilish vaqti jihatidan oldindan bashorat qilish mumkin qiladi.
// Eski yondashuv
DispatchQueue.main.async {
self.updateUI()
}
// @MainActor bilan yangi yondashuv
@MainActor
func updateUI() {
// asosiy oqimda bajariladi
self.label.text = "Yangilandi"
}
| Mezon | @MainActor | DispatchQueue.main |
|---|---|---|
| Tekshirish | kompilyator | runtime |
| Sintaksis | annotatsiya (deklarativ) | chaqiruv (imperativ) |
| Yuk | past (ijrochi almashtirish) | o'rta (closure + navbat) |
| Sinovdan o'tkazish | yuqori (MainActor.shared almashtirilishi mumkin) | past (mock qilish qiyin) |
Haqiqiy iOS loyihalarida @MainActor ViewModel qatlamlarida, SwiftUI ko'rinishlarida va UIKit kontrollerlarida qo'llaniladi. Annotatsiya alohida metodlarga ham, butun turga ham qo'llanilishi mumkin.
Sinfni @MainActor bilan belgilash orqali siz uning barcha metodlari va xususiyatlari faqat asosiy oqimda mavjudligini kafolatlaysiz. Bu ayniqsa SwiftUI ko'rinishlari va ObservableObject sinflari uchun qulay: class dan oldin @MainActor qo'shasiz va barcha @Published xususiyatlari xavfsiz tarzda yangilanadi.
@MainActor
final class UserListViewModel: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
func fetchUsers() async {
isLoading = true
users = await api.getUsers()
isLoading = false
}
}
Oqim almashtirish qo'lda bo'lgan eski UIKit kodi bilan ishlashda, aniq o'tish uchun MainActor.run dan foydalanish mumkin. Bu butun kod bazasini qayta yozmasdan Swift Concurrency-ga bosqichma-bosqich o'tish uchun qulay.
await MainActor.run {
self.tableView.reloadData()
}
Barcha afzalliklariga qaramay, @MainActor ilova arxitekturasini loyihalashda hisobga olinishi muhim bo'lgan bir qator cheklovlarga ega. Qo'llash chegaralarini tushunish noto'g'ri foydalanishni oldini olishga yordam beradi.
Agar butun chaqiruv zanjiri @MainActor bilan belgilangan bo'lsa, har qanday og'ir ish asosiy oqimda bajariladi va UI muzlashiga olib keladi. Faqat UI qatlamini @MainActor bilan belgilash, biznes mantiq va tarmoq so'rovlarini fon aktyorlarida yoki global ijrochida qoldirish tavsiya etiladi.
Eski callback-ga asoslangan APIlar (masalan, async/await siz URLSession) aktyor kontekstini qo'llab-quvvatlamaydi. Integratsiya uchun CheckedContinuation bilan o'rash talab qilinadi. Shuningdek, @MainActor performSelector, target-action va UIKitning boshqa asinxron bo'lmagan naqshlari bilan mos kelmaydi.
@MainActor bilan ilovalarni tuzatishda raqobat holatlarini takrorlash qiyinroq, chunki kompilyator ularning ko'pchiligini runtime-da emas, qurish bosqichida oldini oladi. Biroq, bu soxta xavfsizlik hissi yaratishi mumkin: umumiy mutable ob'ektlar bilan (masalan, NSCache yoki umumiy global o'zgaruvchilar) noto'g'ri ishlash hali ham mumkin, agar ular @MainActor bilan belgilanmagan va aniq sinxronizatsiyasiz ishlatilsa.
@MainActor UI mantig'ini sinovdan o'tkazishni sezilarli darajada soddalashtiradi, chunki testlarda oqimlarni qo'lda almashtirish zaruratini yo'q qiladi. Biroq, birlik va UI testlarini yozishda hisobga olinishi kerak bo'lgan xususiyatlar mavjud.
XCTest da, ijro muhiti avtomatik ravishda asosiy oqim ijrochisini sozlaydi. Test metodi asosiy oqimda bajarilganda, @MainActor funksiyalarini chaqirish qo'shimcha sozlashlarni talab qilmaydi — ular bir xil kontekstda bajariladi. Fon stsenariylarini test qilish uchun Task ichida MainActor.run dan aniq prioritet va ijrochi ko'rsatilgan holda foydalaning, kod fondan chaqirilganda to'g'ri ishlashini alohida tekshirib ko'ring.
Keng tarqalgan yondashuvlardan biri @MainActor bilan ViewModel ni test qilishdir, bunda @Published xususiyatlari asinxron operatsiyalardan keyin to'g'ri yangilanayotgani tekshiriladi. Aktyor kontekstining merosxo'rligi tufayli, test ichidagi await chaqiruvi qo'shimcha DispatchQueue kafolatlari va qo'lda kontekst almashtirishsiz asosiy oqimda bajarilishni kafolatlaydi, bu test yozishni soddalashtiradi.
Mavjud kodni Swift Concurrency-ga refaktor qilishda @MainActor izolyatsiyasini kompilyator orqali tekshiring: @MainActor kontekstidan @MainActor siz sinxron metodlarning har qanday chaqiruvi xato sifatida belgilanadi. Bu xususiyat loyihani bosqichma-bosqich async/await-ga o'tkazish uchun ishlatiladi: ViewModel qatlamini @MainActor sifatida belgilaysiz va kompilyator fon aktyorlariga ko'chirilishi kerak bo'lgan barcha xavfsiz bo'lmagan chaqiruvlarni ajratib ko'rsatadi.
@MainActor bog'liqliklari uchun mocklar yaratishda async-metodli protokollardan foydalaning, ular qaytariladigan turlar bilan asinxron funksiyalarni e'lon qiladi. Bu aktyor izolyatsiyasini buzmasdan tarmoq xizmatlari, ma'lumotlar bazalari va boshqa tashqi bog'liqliklarni almashtirishga imkon beradi. Kompilyator mock izolyatsiya talablariga javob berishini tekshiradi, fon test oqimlaridan @MainActor kodiga tasodifiy kirishni oldini oladi.
@MainActor kodini sinxron sinovdan o'tkazishda asinxron operatsiyalarning tugashini kutish uchun XCTestExpectation dan foydalaning. Testda kutishni o'rnating va asosiy oqimda bajariladigan closure ichida fulfillment-ni bajaring. Agar test cheksiz osilib qolsa — ehtimol, asosiy oqimda chaqiruv sodir bo'lmayapti va aktyor izolyatsiyasini tekshirish kerak. Ijro kontekstini tuzatish uchun test kodi ichida Thread.isMainThread tekshiruvini qo'shish foydalidir.
Tez-tez beriladigan savollar
Yo'q, faqat UI-ni yangilaydigan metodlarni belgilash kifoya. Ammo sinfda bir nechta bunday metodlar bo'lsa, butun sinfga @MainActor qo'shish osonroq. Bu uning barcha a'zolari asosiy oqimda bajarilishini kafolatlaydi va kodni saqlashni soddalashtiradi.
@MainActor — asosiy oqimga bog'langan global aktyorning aniq namunasi. @globalActor — o'z global aktyorlaringizni yaratish uchun protokol. Masalan, loyiha arxitekturasi talab qilsa, fon oqimida kod bajarish uchun @BackgroundActor yaratishingiz mumkin.
Ha, @MainActor bilan sinxron funksiyalar ham asosiy oqimda bajariladi. Biroq, @MainActor-ning asosiy qiymati aynan async/await bilan ochiladi, asinxron funksiya avtomatik ravishda DispatchQueue.main orqali qo'lda o'tishsiz asosiy oqimda qayta boshlanganda.
Task.cancel() @MainActor vazifalari bilan oddiy vazifalar kabi ishlaydi. @MainActor vazifasi Task.isCancelled ni tekshirishi yoki CancellationError ni tashlashi mumkin. Bekor qilishda asosiy oqim bloklanmaydi — vazifa eng yaqin to'xtatish nuqtasida bajarilishini to'xtatadi.
Kompilyator xavfsizlikni kafolatlaydi: @MainActor funksiyasini fon kontekstidan chaqirsangiz, kompilyator xatoni ko'rsatadi. Asinxron chaqiruvlar uchun chaqiruvchi kodni await bilan belgilash kifoya va ijrochi o'zi asosiy oqimga o'tadi. Sinxron chaqiruvlar uchun MainActor.run orqali aniq o'tish talab qilinadi.
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.