@MainActor — ano ito, aplikasyon at mga tampok sa asinkronong code ng Swift

May-akda: IT Sectr Nai-publish: 2026-03-19 Oras ng pagbabasa: 8 min

Ang @MainActor ay isang global na aktor sa wikang Swift na ginagarantiyahan ang pagpapatupad ng code sa pangunahing thread. Ayon sa Apple Developer, 2024, ina-automate ng @MainActor ang paglipat sa pangunahing thread kapag nagtatrabaho sa UI, pinapalaya ang developer mula sa manu-manong pagtawag ng DispatchQueue.main.async. Lumitaw ang anotasyon sa Swift 5.5 kasama ng async/await system.

Mga pangunahing punto

  • @MainActor — global na aktor ng Swift para sa garantiya ng pagpapatupad sa pangunahing thread.
  • Ang async/await system — ang batayan kung saan binuo ang @MainActor.
  • Anotasyon ng klase awtomatikong naglalagay ng lahat ng pamamaraan nito sa pangunahing thread.
  • Hindi tulad ng DispatchQueue.main, sinusuri ng @MainActor ang thread sa antas ng compiler.
  • Mga pag-update ng UI — pangunahing lugar ng aplikasyon ng @MainActor sa iOS development.

Ano ang @MainActor?

@MainActor ay isang global na aktor (global actor) sa Swift na pinagsasama ang mga katangian ng mga aktor na may garantiya ng pagpapatupad sa pangunahing thread ng aplikasyon. Ito ay bahagi ng sistema ng konkurensiya ng Swift, na ipinakilala sa Swift 5.5 kasama ang async/await at structured na konkurensiya. Ang anotasyon ay nagpapahintulot sa developer na huwag mag-isip tungkol sa manu-manong paglipat ng thread at binabawasan ang bilang ng mga error sa UI.

Kahulugan at lugar sa Swift Concurrency

Ang aktor sa Swift ay isang uri ng referensya na naghihiwalay ng estado nito at ginagarantiyahan na isang thread lamang ang maaaring magbago nito. Ang @MainActor ay isang espesyal na global na aktor na ang tagapagpatupad ay ang pangunahing thread. Anumang code na minarkahan ng @MainActor ay isinasagawa sa pangunahing thread — kahit na tinawag ito mula sa isang background na gawain.

Bago ang pagdating ng @MainActor, ang mga developer ay manu-manong lumilipat sa pangunahing thread sa pamamagitan ng DispatchQueue.main.async. Ito ay pinagmulan ng madalas na mga error: nakalimutan ng mga developer na lumipat, na humantong sa mga crash dahil sa pag-update ng UI sa hindi pangunahing thread. Nilulutas ng @MainActor ang problemang ito sa antas ng sistema ng uri.

Mga dahilan ng paglikha

Ang pinagmulan ng karamihan sa mga bug sa mga aplikasyon ng iOS ay kawalan ng kaligtasan ng UI — pag-update ng interface mula sa isang background na thread. Isinama ng Apple ang @MainActor sa Swift Concurrency upang gawing awtomatiko at masusuri ng compiler ang paglipat sa pangunahing thread, inaalis ang isang buong klase ng mga error sa runtime.

Paano gumagana ang @MainActor?

Prinsipyo ng paggana ng @MainActor ay batay sa sistema ng pagpapatupad ng Swift Concurrency. Kapag ang isang thread ay tumawag ng isang function na minarkahan ng @MainActor, isinasuspinde ito ng tagapag-iskedyul sa kasalukuyang tagapagpatupad at ipinagpatuloy ito sa pangunahing thread. Sinusubaybayan ng compiler ang mga hangganan ng tawag at ginagarantiyahan ang kaligtasan.

Tagapagpatupad ng pangunahing thread

Para sa pagpapatupad ng @MainActor ay responsable ang MainActor.shared — ang tagapagpatupad na nauugnay sa pangunahing thread ng aplikasyon. Kapag ang isang asinkronong function ay minarkahan ng @MainActor, ito ay palaging ipinagpatuloy sa tagapagpatupad na ito, hindi alintana kung saang thread sinimulan ang orihinal na gawain.

swift
import SwiftUI

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

    @MainActor
    func loadData() async {
        let result = await fetchRemoteData()
        items = result  // ligtas, ginagarantiyahan ng MainActor ang pangunahing thread
    }
}

Pagmamana ng konteksto ng aktor

Kung ang isang function ay minarkahan ng @MainActor at tumawag ng isa pang asinkronong function, bilang default ay nagmamana ito ng konteksto ng aktor. Nangangahulugan ito na ang lahat ng nested na tawag ay isinasagawa din sa pangunahing thread, maliban kung iba ang tinukoy. Sinusubaybayan ito ng compiler at nagbibigay ng error kapag sinubukang magpasa ng hindi tugmang closure.

@MainActor vs DispatchQueue.main

Ang paghahambing ng @MainActor at DispatchQueue.main ay tumutulong na maunawaan kung bakit ang bagong mekanismo ay itinuturing na mas ligtas at maginhawa, kahit na pareho silang lumulutas ng parehong gawain — pagpapatupad ng code sa pangunahing thread.

Kaligtasan sa antas ng uri

Ang @MainActor ay isang pagsusuri sa antas ng compiler. Kung susubukan mong tumawag ng @MainActor function mula sa isang hindi ligtas na konteksto, ang compiler ay magbibigay ng babala o error. Ang DispatchQueue.main.async ay isang runtime na tawag: ang code ay magko-compile, ngunit maaaring mag-crash sa runtime kapag sinusubukang i-update ang UI mula sa isang background na thread.

Pagganap at kalabisan

Ang DispatchQueue.main.async ay nagdaragdag ng isang bloke sa pila na maaaring isagawa nang may pagkaantala. Ang @MainActor na may async/await ay nagsasagawa ng direktang paglipat ng tagapagpatupad nang hindi lumilikha ng mga karagdagang closure. Binabawasan nito ang overhead at ginagawang mas predictable ang code sa mga tuntunin ng oras ng pagpapatupad.

swift
// Lumang approach
DispatchQueue.main.async {
    self.updateUI()
}

// Bagong approach gamit ang @MainActor
@MainActor
func updateUI() {
    // isinasagawa sa pangunahing thread
    self.label.text = "Na-update"
}
Kriterya@MainActorDispatchQueue.main
Pagsusuricompilerruntime
Sintaksanotasyon (deklaratibo)tawag (imperatibo)
Overheadmababa (paglipat ng tagapagpatupad)katamtaman (closure + pila)
Kakayahang masurimataas (MainActor.shared ay maaaring palitan)mababa (mahirap i-mock)

Paggamit ng @MainActor sa mga proyektong iOS

Sa mga totoong iOS na proyekto, ang @MainActor ay inilalapat sa mga layer ng ViewModel, SwiftUI view at UIKit controller. Ang anotasyon ay maaaring ilapat sa parehong indibidwal na pamamaraan at buong uri.

Anotasyon ng klase o istraktura

Sa pamamagitan ng pagmamarka ng isang klase na may @MainActor, ginagarantiyahan mo na ang lahat ng pamamaraan at katangian nito ay maa-access lamang sa pangunahing thread. Ito ay lalong maginhawa para sa SwiftUI view at ObservableObject na mga klase: idaragdag mo lang ang @MainActor bago ang class, at lahat ng @Published na katangian ay ligtas na na-update.

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
    }
}

Pagbabalot ng legacy code

Kapag nagtatrabaho sa lumang UIKit code, kung saan ang paglipat ng thread ay manu-mano, maaaring gamitin ang MainActor.run para sa tahasang paglipat. Ito ay maginhawa para sa unti-unting paglipat sa Swift Concurrency nang hindi muling isinusulat ang buong codebase.

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

Mga limitasyon ng @MainActor

Sa kabila ng lahat ng mga pakinabang, ang @MainActor ay may ilang mga limitasyon na mahalagang isaalang-alang kapag nagdidisenyo ng arkitektura ng aplikasyon. Ang pag-unawa sa mga hangganan ng aplikasyon ay tumutulong na maiwasan ang maling paggamit.

Pagganap sa masinsinang paggamit

Kung ang buong chain ng tawag ay minarkahan ng @MainActor, ang anumang mabigat na trabaho ay isasagawa sa pangunahing thread, na magdudulot ng pag-freeze ng UI. Inirerekomenda na markahan lamang ang UI layer ng @MainActor, at iwanan ang business logic at network request sa background na aktor o global na tagapagpatupad.

Hindi pagkakatugma sa ilang API

Ang mga lumang API na nakabatay sa callback (hal. URLSession nang walang async/await) ay hindi sumusuporta sa konteksto ng aktor. Para sa pagsasama, kinakailangan ang isang wrapper na may CheckedContinuation. Gayundin, ang @MainActor ay hindi tugma sa performSelector, target-action at iba pang hindi asinkronong pattern ng UIKit.

Multi-thread na debugging

Kapag nagde-debug ng mga aplikasyon na may @MainActor, mas mahirap i-reproduce ang mga kondisyon ng race, dahil pinipigilan ng compiler ang marami sa kanila sa yugto ng pagbuo, hindi sa runtime. Gayunpaman, maaari itong lumikha ng maling pakiramdam ng seguridad: ang hindi tamang pagtatrabaho sa mga shared mutable na bagay (hal. NSCache o shared global variable) ay posible pa rin kung hindi sila minarkahan ng @MainActor at ginamit nang walang tahasang synchronisasyon.

Pagsubok ng @MainActor

@MainActor ay makabuluhang pinapasimple ang pagsubok ng UI logic, dahil inaalis nito ang pangangailangan para sa manu-manong paglipat ng thread sa mga pagsubok. Gayunpaman, may mga tampok na dapat isaalang-alang kapag nagsusulat ng mga unit test at UI test.

Mga unit test na may MainActor

Sa XCTest, ang kapaligiran ng pagpapatupad ay awtomatikong nagko-configure ng tagapagpatupad ng pangunahing thread. Kapag ang test method ay isinasagawa sa pangunahing thread, ang pagtawag ng mga @MainActor function ay hindi nangangailangan ng karagdagang setup — sila ay isinasagawa sa parehong konteksto. Para sa pagsubok ng mga background scenario, gamitin ang MainActor.run sa loob ng Task na may tahasang pagtukoy ng priyoridad at tagapagpatupad, hiwalay na suriin na ang code ay gumagana nang tama kapag tinawag mula sa background.

Ang isa sa mga karaniwang approach ay ang pagsubok ng ViewModel na may @MainActor, kung saan sinusuri na ang @Published na mga katangian ay na-update nang tama pagkatapos ng mga asinkronong operasyon. Dahil sa pagmamana ng konteksto ng aktor, ang tawag na await sa loob ng test ay ginagarantiyahan ang pagpapatupad sa pangunahing thread nang walang karagdagang DispatchQueue na garantiya at manu-manong paglipat ng konteksto, na nagpapasimple sa pagsulat ng mga pagsubok.

Pagsusuri ng isolasyon sa panahon ng refactoring

Kapag nire-refactor ang umiiral na code sa Swift Concurrency, suriin ang isolasyon ng @MainActor sa pamamagitan ng compiler: anumang tawag ng mga synchronous na pamamaraan nang walang @MainActor mula sa @MainActor na konteksto ay minarkahan bilang error. Ang katangiang ito ay ginagamit para sa unti-unting paglipat ng proyekto sa async/await: minarkahan mo ang ViewModel layer bilang @MainActor, at itinatampok ng compiler ang lahat ng hindi ligtas na tawag na kailangang ilipat sa background na mga aktor.

Mocking at konteksto ng aktor

Kapag lumilikha ng mga mock para sa @MainActor dependencies, gumamit ng mga protocol na may async na pamamaraan na nagdedeklara ng mga asinkronong function na may mga return type. Pinapayagan nito ang pagpapalit ng mga network service, database at iba pang panlabas na dependencies nang hindi lumalabag sa aktor na isolasyon. Susuriin ng compiler na ang mock ay nakakatugon sa lahat ng mga kinakailangan sa isolasyon, na pumipigil sa hindi sinasadyang pag-access sa @MainActor code mula sa background test threads.

Paghihintay para sa mga asinkronong operasyon

Kapag sinusubok nang synchronous ang @MainActor code, gamitin ang XCTestExpectation para maghintay ng pagkumpleto ng mga asinkronong operasyon. Itakda ang inaasahan sa test at gawin ang fulfillment sa loob ng closure na isinasagawa sa pangunahing thread. Kung ang test ay nakabitin nang walang katapusan — malamang na ang tawag sa pangunahing thread ay hindi nangyayari at kailangang suriin ang aktor na isolasyon. Para sa debugging ng konteksto ng pagpapatupad, kapaki-pakinabang na magdagdag ng pagsusuri ng Thread.isMainThread sa loob ng test code.

Mga madalas itanong

Kailangan bang markahan ang buong klase ng @MainActor?

Hindi, sapat na markahan lamang ang mga pamamaraan na nag-a-update ng UI. Gayunpaman, kung maraming ganoong pamamaraan sa klase, mas madaling idagdag ang @MainActor sa buong klase. Ginagarantiyahan nito na ang lahat ng miyembro nito ay isinasagawa sa pangunahing thread at pinapasimple ang pagpapanatili ng code.

Ano ang pagkakaiba ng @MainActor sa @globalActor?

@MainActor ay isang kongkretong instance ng global na aktor, na nakatali sa pangunahing thread. Ang @globalActor ay isang protocol para sa paglikha ng iyong sariling global na mga aktor. Halimbawa, maaari kang lumikha ng @BackgroundActor para sa pagpapatupad ng code sa isang background na thread, kung kinakailangan ito ng arkitektura ng proyekto.

Maaari bang gamitin ang @MainActor nang walang async/await?

Oo, ang mga synchronous function na may @MainActor ay isinasagawa din sa pangunahing thread. Gayunpaman, ang pangunahing halaga ng @MainActor ay nahahayag sa async/await, kapag ang asinkronong function ay awtomatikong ipinagpatuloy sa pangunahing thread nang walang manu-manong paglipat sa pamamagitan ng DispatchQueue.main.

Paano kanselahin ang isang @MainActor na gawain?

Task.cancel() ay gumagana sa @MainActor na mga gawain tulad ng sa mga ordinaryong gawain. Ang @MainActor na gawain ay maaaring suriin ang Task.isCancelled o magtapon ng CancellationError. Sa pagkansela, ang pangunahing thread ay hindi nahaharang — ang gawain ay humihinto lamang sa pagpapatupad sa pinakamalapit na suspension point.

Ano ang mangyayari kung ang @MainActor ay tinawag mula sa isang background na thread?

Ang compiler ay ginagarantiyahan ang kaligtasan: kung tatawag ka ng @MainActor function mula sa isang background na konteksto, ituturo ng compiler ang error. Para sa mga asinkronong tawag, sapat na markahan ang tumatawag na code ng await, at ang tagapagpatupad ay lilipat mismo sa pangunahing thread. Para sa mga synchronous na tawag, kinakailangan ang tahasang paglipat sa pamamagitan ng MainActor.run.

Buod

  • @MainActor — global na aktor ng Swift na ginagarantiyahan ang pagpapatupad sa pangunahing thread.
  • Pagsusuri ng compiler ay nag-aalis ng isang buong klase ng mga error sa kaligtasan ng UI.
  • Anotasyon ng buong klase awtomatikong naglalagay ng lahat ng pamamaraan nito sa pangunahing thread.
  • MainActor.run — tahasang paglipat para sa legacy code at synchronous na konteksto.
  • Hindi tulad ng DispatchQueue.main, ang @MainActor ay hindi lumilikha ng mga closure at gumagamit ng paglipat ng tagapagpatupad.
  • Ang mabibigat na pag-compute ay hindi dapat isagawa sa ilalim ng @MainActor upang maiwasan ang pag-freeze ng UI.
  • Pagmamana ng konteksto ng aktor ay nagpapasimple ng mga chain ng asinkronong tawag at ginagawang sequential, predictable at ligtas ang code para sa UI.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din