@MainActor — bu nədir, tətbiqi və Swift asinxron kodunda xüsusiyyətləri

Müəllif: IT Sectr Dərc olunub: 2026-03-19 Oxuma vaxtı: 8 dəq

@MainActor Swift dilində qlobal aktordur, kodun əsas axında icrasını təmin edir. Apple Developer, 2024-ə görə, @MainActor UI ilə işləyərkən əsas axına keçidi avtomatlaşdırır, proqramçını DispatchQueue.main.async əl çağırışından azad edir. Annotasiya Swift 5.5-də async/await sistemi ilə birlikdə meydana çıxdı.

Əsas məqamlar

  • @MainActor — Swift-də əsas axında icranı təmin edən qlobal aktor.
  • async/await sistemi — @MainActor-un işləməsinin əsası.
  • Sinif annotasiyası bütün metodlarını avtomatik olaraq əsas axına yerləşdirir.
  • DispatchQueue.main-dən fərqli olaraq, @MainActor axını kompilyator səviyyəsində yoxlayır.
  • UI yeniləmələri — @MainActor-un iOS inkişafında əsas tətbiq sahəsi.

@MainActor nədir?

@MainActor Swift-də qlobal aktordur (global actor) və aktorların xüsusiyyətlərini tətbiqin əsas axınında icra zəmanəti ilə birləşdirir. Swift 5.5-də async/await vɘ strukturlu paralelliklə təqdim edilmiş Swift paralellik sisteminin bir hissəsidir. Annotasiya proqramçıya axınları əl ilə dəyişmək barədə düşünməməyə imkan verir vɘ UI səhvlərinin sayını azaldır.

Tərif vɘ Swift Concurrency-də yeri

Swift-dɘ aktor — vɘziyyətini izolə edən vɘ yalnız bir axının onu dəyişə biləcəyinɘ zəmanɘt verən istinad tipidir. @MainActor — icraçısı əsas axın olan xüsusi qlobal aktordur. @MainActor ilɘ işarələnmiş istənilən kod əsas axında icra olunur — hətta fon tapşırığından çağırılsa belə.

@MainActor-dan əvvəl proqramçılar DispatchQueue.main.async vasitəsilə əl ilə əsas axına keçirdilər. Bu tez-tez səhvlərə səbɘb olurdu: proqramçılar keçidi unudur, UI-nı qeyri-əsas axında yeniləyərək çökmələrə yol açırdılar. @MainActor bu problemi tip sistemi səviyyəsindɘ həll edir.

Yaranma səbəbləri

iOS tətbiqlərindəki səhvlərin əksəriyyətinin mənbəyi UI-təhlükəsizlik — interfeysin fon axınından yenilənməsidir. Apple @MainActor-u Swift Concurrency-yə daxil etdi ki, əsas axına keçid avtomatik vɘ kompilyator tərəfindən yoxlanılan olsun vɘ runtime səhvlərinin bütün sinfini aradan qaldırsın.

@MainActor necə işləyir?

İş prinsipi Swift Concurrency icra sisteminə əsaslanır. Axın @MainActor ilə işarələnmiş funksiyanı çağırdıqda, planlaşdırıcı onu cari icraçıda dayandırır vɘ əsas axında bərpa edir. Kompilyator çağırış sərhədlərini izləyir vɘ təhlükəsizliyi təmin edir.

Əsas axın icraçısı

@MainActor-un icrasına MainActor.shared cavabdehdir — tətbiqin əsas axını ilə əlaqəli icraçı. Asinxron funksiya @MainActor ilə işarələndikdə, o, həmişə bu icraçıda bərpa olunur, orijinal tapşırığın hansı axında başladılmasından asılı olmayaraq.

swift
import SwiftUI

class ViewModel: ObservableObject {
    @Published var items: [String] = []

    @MainActor
    func loadData() async {
        let result = await fetchRemoteData()
        items = result  // təhlükəsiz, MainActor əsas axını təmin edir
    }
}

Aktor kontekstinin vərəsəliyi

Əgər funksiya @MainActor ilə işarələnibsə vɘ başqa bir asinxron funksiyanı çağırırsa, o, defolt olaraq aktor kontekstini miras alır. Bu o deməkdir ki, bütün iç-içə çağırışlar da əsas axında icra olunur, əks hal göstərilməyibsə. Kompilyator bunu izləyir vɘ uyğun olmayan closure ötürülməsi cəhdindɘ səhv verir.

@MainActor vs DispatchQueue.main

@MainActor vɘ DispatchQueue.main müqayisəsi yeni mexanizmin niyə daha təhlükəsiz vɘ rahat hesab edildiyini anlamağa kömək edir, baxmayaraq ki, hər ikisi eyni tapşırığı — kodun əsas axında icrasını — həll edir.

Tip səviyyəsindɘ təhlükəsizlik

@MainActor — kompilyator səviyyəsindɘ yoxlamadır. @MainActor funksiyasını təhlükəsiz olmayan kontekstdɘn çağırmağa çalışsanz, kompilyator xəbərdarlıq vɘ ya sɘhv verir. DispatchQueue.main.async — runtime çağırışıdır: kod kompilyasiya olunacaq, lakin UI-nı fon axınından yeniləməyɘ çalışdıqda runtime-da çökə bilər.

Performans vɘ artıqlıq

DispatchQueue.main.async növbəyə gecikmə ilə icra oluna bilən blok əlavə edir. @MainActor async/await ilə birbaşa icraçı dəyişməsi həyata keçirir, lazımsız closure-lar yaratmadan. Bu, yükü azaldır vɘ kodu icra müddəti baxımından daha proqnozlaşdırılan edir.

swift
// Köhnə yanaşma
DispatchQueue.main.async {
    self.updateUI()
}

// @MainActor ilə yeni yanaşma
@MainActor
func updateUI() {
    // əsas axında icra olunur
    self.label.text = "Yeniləndi"
}
Meyar@MainActorDispatchQueue.main
Yoxlamakompilyatorruntime
İstifadəannotasiya (deklarativ)çağırış (imperativ)
Yükaz (icraçı dəyişməsi)orta (closure + növbə)
Test edilə bilənlikyüksək (MainActor.shared əvəz edilə bilər)aşağı (mock etmək çətindir)

iOS layihələrində @MainActor istifadəsi

Real iOS layihələrində @MainActor ViewModel qatlarında, SwiftUI görünüşlərində vɘ UIKit kontrollerlərində tətbiq edilir. Annotasiya həm ayrı-ayrı metodlara, həm də bütün tipə tətbiq oluna bilər.

Sinif vɘ ya strukturun annotasiyası

Sinif @MainActor ilə işarələməklə, bütün metodlarının vɘ xüsusiyyətlərinin yalnız əsas axında əlçatan olduğunu təmin edirsiniz. Bu, xüsusilə SwiftUI görünüşləri vɘ ObservableObject sinifləri üçün əlverişlidir: sadəcə class-dan əvvəl @MainActor əlavə edirsiniz vɘ bütün @Published xüsusiyyətləri təhlükəsiz şəkildə yenilənir.

swift
@MainActor
final class UserListViewModel: ObservableObject {
    @Published var users: [User] = []
    @Published var isLoading = false

    func fetchUsers() async {
        isLoading = true
        users = await api.getUsers()
        isLoading = false
    }
}

Legacy kodun bükülməsi

Axın keçidinin əl ilə edildiyi köhnə UIKit kodu ilə işləyərkɘn, aŝkarlıq keçid üçün MainActor.run istifadə edilə bilər. Bu, bütün kod bazasını yenidən yazmadan Swift Concurrency-yə tədricən keçid üçün əlverişlidir.

swift
await MainActor.run {
    self.tableView.reloadData()
}

@MainActor-un məhdudiyyətləri

Bütün üstünlüklərə baxmayaraq, @MainActor tətbiqin arxitekturasını layihələşdirərkɘn nəzərə alınması vacib olan bir sıra məhdudiyyətlərɘ malikdir. Tətbiq sərhədlərini anlamaq düzgün olmayan istifadɘnin qarşısını almağa kömək edir.

Gərgin istifadədɘ performans

Bütün çağırış zənciri @MainActor ilə işarələnmişsɘ, hər bir ağır iş əsas axında icra olunacaq, UI-nın donmasına sɘbɘb olacaq. Yalnız UI qatını @MainActor ilə işarələmək, biznes məntiqini vɘ şəbəkə sorğularını fon aktorlarında vɘ ya qlobal icraçıda buraxmaq tövsiyɘ olunur.

Bəzi API-lərlə uyğunsuzluq

Köhnə callback-based API-lər (məsələn, async/await olmadan URLSession) aktor kontekstini dəstəkləmir. İnteqrasiya üçün CheckedContinuation ilə bükülmə tələb olunur. Həmçinin @MainActor performSelector, target-action vɘ UIKit-in digər qeyri-asinxron nümunələri ilə uyğun deyil.

Çoxaxınlı debug

@MainActor ilə tətbiqləri debug edərkɘn yarışma hallarını təkrarlamaq daha çətindir, çünki kompilyator onların çoxunun qarşısını runtime-da deyil, qurma mərhələsindɘ alır. Lakin bu, yalançı təhlükəsizlik hissi yarada bilər: paylaşılan mutable obyektlərlə (məsələn, NSCache vɘ ya ümumi qlobal dəyişənlər) səhv iş hələ də mümkündür, əgər onlar @MainActor ilə işarələnməyibsɘ vɘ aşkar sinxronizasiya olmadan istifadɘ olunursa.

@MainActor-un test edilməsi

@MainActor UI məntiqinin test edilməsini əhəmiyyɘtli dərəcədɘ asanlaşdırır, çünki testlərdɘ axınları əl ilə dəyişmək ehtiyacını aradan qaldırır. Bununla belɘ, vahid vɘ UI testləri yazarkɘn nəzərə alınmalı olan xüsusiyyɘtlər var.

MainActor ilə vahid testlər

XCTest-dɘ icra mühiti avtomatik olaraq əsas axın icraçısını konfiqurasiya edir. Test metodu əsas axında işə salındıqda, @MainActor funksiyalarını çağırmaq əlavə qurulum tələb etmir — onlar eyni kontekstdɘ icra olunur. Fon ssenarilərini test etmək üçün Task içərisindɘ MainActor.run-dan aşkar prioritet vɘ icraçı göstərilməklə istifadɘ edin, kodun fondan çağırıldıqda düzgün işlədiyini ayrıca yoxlayın.

Ümumi yanaşmalardan biri @MainActor ilə ViewModel test etməkdir, burada @Published xüsusiyyətlərinin asinxron əməliyyatlardan sonra düzgün yeniləndiyi yoxlanılır. Aktor kontekstinin miras qalması sayəsindɘ, test daxilindɘ await çağırışı əlavə DispatchQueue zəmanɘtləri vɘ əl kontekst dəyişməsi olmadan əsas axında icranı təmin edir, bu da test yazmağı asanlaşdırır.

Refaktoring zamanı izolyasiyanın yoxlanması

Mövcud kodu Swift Concurrency-yə refaktor edərkɘn @MainActor izolyasiyasını kompilyator vasitəsilə yoxlayın: @MainActor kontekstindɘn @MainActor olmadan sinxron metodların çağırılması səhv kimi qeyd olunur. Bu xüsusiyyɘt layihəni tədricən async/await-ə keçirmək üçün istifadɘ olunur: ViewModel qatını @MainActor kimi işarələyirsiniz vɘ kompilyator fon aktorlarına köçürülməsi lazım olan bütün təhlükəsiz olmayan çağırışları vurğulayır.

Mock vɘ aktor konteksti

@MainActor asılılıqları üçün mocklar yaradarkən async-metodları olan protokollardan istifadɘ edin, onlar qaytarılma tipləri ilə asinxron funksiyalar bəyan edir. Bu, aktor izolyasiyasını pozmadan şəbəkə xidmətlərini, verilənlər bazalarını vɘ digər xarici asılılıqları əvəz etməyə imkan verir. Kompilyator mock-un izolyasiya tələblərinə cavab verdiyini yoxlayacaq, fon test axınlarından @MainActor koduna təsadüfi girişin qarşısını alacaq.

Asinxron əməliyyatların gözlənilməsi üçün Wait

@MainActor kodunun sinxron test edilməsi zamanı asinxron əməliyyatların tamamlanmasını gözləmək üçün XCTestExpectation istifadɘ edin. Testdɘ gözləmə təyin edin vɘ əsas axında icra olunan closure daxilindɘ fulfillment həyata keçirin. Test sonsuz olaraq asılı qalarsa — çox güman ki, əsas axında çağırış baş vermir vɘ aktor izolyasiyasını yoxlamaq lazımdır. İcra kontekstinin debug edilməsi üçün test kodunun daxilindɘ Thread.isMainThread yoxlanışı əlavə etmək faydalıdır.

Tez-tez verilən suallar

Bütün sinfi @MainActor ilə işarələmək məcburidirmi?

Xeyr, yalnız UI-nı yeniləyən metodları işarələmək kifayətdir. Lakin sinifdɘ bir neçə belɘ metod varsa, bütün sinfɘ @MainActor əlavə etmək daha asandır. Bu, onun bütün üzvlərinin əsas axında icra olunmasını təmin edir vɘ kodun saxlanmasını asanlaşdırır.

@MainActor @globalActor-dan nə ilə fərqlənir?

@MainActor — əsas axına bağlı olan qlobal aktorun konkret nümunəsidir. @globalActor — öz qlobal aktorlarınızı yaratmaq üçün protokoldur. Məsələn, layihənin arxitekturası tələb edirsə, fon axınında kod icrası üçün @BackgroundActor yarada bilərsiniz.

@MainActor async/await olmadan istifadə edilə bilərmi?

Bəli, @MainActor ilə sinxron funksiyalar da əsas axında icra olunur. Lakin @MainActor-un ɘsas dəyəri məhz async/await ilə aşkarlanır, asinxron funksiya avtomatik olaraq DispatchQueue.main vasitəsilə əl keçidi olmadan əsas axında bərpa olunur.

@MainActor tapşırığını ləğv etmək olarmı?

Task.cancel() @MainActor tapşırıqları ilə adi tapşırıqlarla eyni şəkildə işləyir. @MainActor tapşırığı Task.isCancelled yoxlaya vɘ ya CancellationError atıa bilər. Ləğv edildikdɘ əsas axın bloklanmır — tapşırıq sadəcɘ ən yaxın dayanma nöqtəsindɘ icrasını dayandırır.

Fon axınından @MainActor çağırılsa nə olar?

Kompilyator təhlükəsizliyi təmin edir: @MainActor funksiyasını fon kontekstindɘn çağırsanız, kompilyator sɘhvi göstərəcək. Asinxron çağırışlar üçün çağıran kodu await ilə işarələmək kifayətdir vɘ icraçı özü əsas axına keçəcək. Sinxron çağırışlar üçün MainActor.run vasitəsilə aşkar keçid təlɘb olunur.

Nəticə

  • @MainActor — Swift-dɘ əsas axında icranı təmin edən qlobal aktor.
  • Kompilyator yoxlaması UI təhlükəsizlik səhvlərinin bütün sinfini aradan qaldırır.
  • Bütün sinfin annotasiyası onun bütün metodlarını avtomatik olaraq əsas axına yerləşdirir.
  • MainActor.run — legacy kod vɘ sinxron kontekstlər üçün aşkar keçid.
  • DispatchQueue.main-dɘn fɘrqli olaraq, @MainActor closure yaratmır vɘ icraçı dəyişməsindən istifadɘ edir.
  • Ağır hesablamalar UI donmalarının qarşısını almaq üçün @MainActor altında icra olunmamalıdır.
  • Aktor kontekstinin miras qalması asinxron çağırış zəncirlərini sadələşdirir vɘ kodu ardıcıl, proqnozlaşdırılan vɘ UI üçün təhlükəsiz edir.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun