Înainte de apariția actorilor, sincronizarea stării partajate între multiple fire de execuție necesita primitive manuale predispuse la erori fatale: NSLock, os_unfair_lock sau cozi seriale DispatchQueue. O singură citire sau scriere nesincronizată ducea la corupere de memorie sau crash-uri imprevizibile.
În Swift, Actorii (actor) sunt tipuri de referință (similare claselor) care garantează izolarea completă a stării mutabile: compilatorul interzice accesul sincron direct la proprietățile actorului din afara domeniului său de izolare, forțând serializarea apelurilor prin await.
// Actorul protejează starea internă 'balanta' împotriva oricărui Data Race:
actor ContBancar {
let numarCont: String // Proprietate imutabilă (Sendable)
private var sold: Double = 0.0 // Stare mutabilă izolată
init(numarCont: String, soldInitial: Double) {
self.numarCont = numarCont
self.sold = soldInitial
}
// Metodele interne pot citi și scrie 'sold' în mod sincron:
func depunere(suma: Double) {
sold += suma
}
func retragere(suma: Double) -> Bool {
guard sold >= suma else { return false }
sold -= suma
return true
}
// Cuvântul cheie 'nonisolated' permite apelul sincron din exterior pentru date sigure:
nonisolated var infoPublica: String {
return "Cont IBAN: \(numarCont)"
}
}
// Apelul din exterior este întotdeauna asincron:
func efectueazaOperatiune(pe cont: ContBancar) async {
// Acces sincron la proprietatea nonisolated:
print(cont.infoPublica)
// Acces asincron protejat la logica internă mutabilă:
await cont.depunere(suma: 250.0)
let reusit = await cont.retragere(suma: 100.0)
print("Retragere finalizată cu succes: \(reusit)")
}
Global Actorul @MainActor
Platformele Apple impun ca toate modificările asupra interfeței grafice să se execute exclusiv pe firul principal de execuție (Main Thread). Adnotarea @MainActor este un actor global care forțează compilatorul să garanteze că metodele, proprietățile sau întregile clase adnotate rulează pe firul de UI:
@MainActor
final class ArticoleViewModel: ObservableObject {
@Published var articole: [String] = []
func incarcaArticole() async {
// Operația grea de rețea rulează pe thread pool cooperativ de fundal:
let date = await descarcaDePeServer()
// Atribuirea are loc automat pe Main Thread, fără DispatchQueue.main.async manual!
self.articole = date
}
}