@MainActor — nedir, Swift asenkron kodunda uygulaması ve özellikleri

Yazar: IT Sectr Yayınlanma: 2026-03-19 Okuma süresi: 8 dk

@MainActor, Swift dilinde ana iş parçacığında kod yürütülmesini garanti eden küresel bir aktördür. Apple Developer, 2024'e göre, @MainActor, UI ile çalışırken ana iş parçacığına geçişi otomatikleştirerek geliştiricinin manuel olarak DispatchQueue.main.async çağrısı yapmasını ortadan kaldırır. Ek açıklama, Swift 5.5'te async/await sistemiyle birlikte ortaya çıktı.

Önemli Noktalar

  • @MainActor — ana iş parçacığında yürütmeyi garanti eden küresel bir Swift aktörü.
  • async/await sistemi — @MainActor'ın üzerine inşa edildiği temel.
  • Sınıf ek açıklaması tüm metotlarını otomatik olarak ana iş parçacığına yerleştirir.
  • DispatchQueue.main'den farklı olarak, @MainActor iş parçacığını derleyici seviyesinde kontrol eder.
  • UI güncellemeleri — iOS geliştirmede @MainActor'ın ana uygulama alanı.

@MainActor nedir?

@MainActor, Swift'te aktörlerin özelliklerini uygulamanın ana iş parçacığında yürütme garantisiyle birleştiren küresel bir aktördür. Swift 5.5'te async/await ve yapılandırılmış eşzamanlılık ile birlikte tanıtılan Swift eşzamanlılık sisteminin bir parçasıdır. Ek açıklama, geliştiricinin manuel iş parçacığı geçişi hakkında düşünmesine gerek bırakmaz ve UI hatalarının sayısını azaltır.

Swift Concurrency'de tanım ve yeri

Swift'te aktör, durumunu yalıtan ve yalnızca bir iş parçacığının onu değiştirebilmesini garanti eden bir referans türüdür. @MainActor, yürütücüsü ana iş parçacığı olan özel bir küresel aktördür. @MainActor ile işaretlenmiş herhangi bir kod, arka plan görevinden çağrılmış olsa bile ana iş parçacığında yürütülür.

@MainActor'dan önce, geliştiriciler DispatchQueue.main.async aracılığıyla manuel olarak ana iş parçacığına geçiş yapıyordu. Bu, sık hataların kaynağıydı: geliştiriciler geçiş yapmayı unutuyor ve ana iş parçacığı dışında UI güncellemesi nedeniyle çökmelere yol açıyordu. @MainActor bu sorunu tür sistemi seviyesinde çözer.

Oluşturulma nedenleri

iOS uygulamalarındaki hataların çoğunun kaynağı UI güvensizliğidir — arayüzün arka plan iş parçacığından güncellenmesi. Apple, @MainActor'ı Swift Concurrency'e dahil ederek ana iş parçacığına geçişi otomatik ve derleyici tarafından kontrol edilebilir hale getirdi ve böylece bir runtime hata sınıfını tamamen ortadan kaldırdı.

@MainActor nasıl çalışır?

@MainActor'ın çalışma prensibi Swift Concurrency yürütme sistemine dayanır. Bir iş parçacığı @MainActor ile işaretlenmiş bir işlevi çağırdığında, zamanlayıcı onu mevcut yürütücüde askıya alır ve ana iş parçacığında devam ettirir. Derleyici, çağrı sınırlarını izler ve güvenliği garanti eder.

Ana iş parçacığı yürütücüsü

@MainActor'ın yürütülmesi, uygulamanın ana iş parçacığıyla ilişkili bir yürütücü olan MainActor.shared tarafından yönetilir. Asenkron bir işlev @MainActor ile işaretlendiğinde, orijinal görevin hangi iş parçacığında başlatıldığına bakılmaksızın her zaman bu yürütücüde devam eder.

swift
import SwiftUI

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

    @MainActor
    func loadData() async {
        let result = await fetchRemoteData()
        items = result  // güvenle, MainActor ana iş parçacığını garanti eder
    }
}

Aktör bağlamı mirası

Bir işlev @MainActor ile işaretlenmişse ve başka bir asenkron işlevi çağırıyorsa, varsayılan olarak aktör bağlamını miras alır. Bu, aksi belirtilmedikçe tüm iç içe çağrıların da ana iş parçacığında yürütüldüğü anlamına gelir. Derleyici bunu izler ve tutarsız bir closure geçirmeye çalışıldığında hata verir.

@MainActor vs DispatchQueue.main

@MainActor ve DispatchQueue.main karşılaştırması, her ikisi de aynı görevi — ana iş parçacığında kod yürütmeyi — çözmesine rağmen, yeni mekanizmanın neden daha güvenli ve kullanışlı kabul edildiğini anlamaya yardımcı olur.

Tür seviyesinde güvenlik

@MainActor, derleyici seviyesinde bir kontroldür. Güvenli olmayan bir bağlamdan @MainActor işlevini çağırmaya çalışırsanız, derleyici bir uyarı veya hata verecektir. DispatchQueue.main.async bir runtime çağrısıdır: kod derlenecek ancak arka plan iş parçacığından UI güncellemeye çalışıldığında runtime'da çökebilir.

Performans ve ek yük

DispatchQueue.main.async, kuyruğa gecikmeyle yürütülebilecek bir blok ekler. @MainActor async/await ile gereksiz closure'lar oluşturmadan doğrudan yürütücü geçişi yapar. Bu, ek yükü azaltır ve yürütme süresini daha öngörülebilir hale getirir.

swift
// Eski yaklaşım
DispatchQueue.main.async {
    self.updateUI()
}

// @MainActor ile yeni yaklaşım
@MainActor
func updateUI() {
    // ana iş parçacığında yürütülür
    self.label.text = "Güncellendi"
}
Kriter@MainActorDispatchQueue.main
Kontrolderleyiciruntime
Sözdizimiek açıklama (bildirimsel)çağrı (emredici)
Ek yükdüşük (yürütücü geçişi)orta (closure + kuyruk)
Test edilebilirlikyüksek (MainActor.shared değiştirilebilir)düşük (mock'laması zor)

iOS projelerinde @MainActor kullanımı

Gerçek iOS projelerinde, @MainActor ViewModel katmanlarında, SwiftUI görünümlerinde ve UIKit denetleyicilerinde kullanılır. Ek açıklama hem tek tek metotlara hem de tüm tipe uygulanabilir.

Sınıf veya yapı ek açıklaması

Bir sınıfı @MainActor ile işaretleyerek, tüm metotlarının ve özelliklerinin yalnızca ana iş parçacığında erişilebilir olmasını garanti edersiniz. Bu, SwiftUI görünümleri ve ObservableObject sınıfları için özellikle kullanışlıdır: sınıfın önüne @MainActor eklemeniz yeterlidir ve tüm @Published özellikleri güvenle güncellenir.

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

Eski kodu sarma

İş parçacığı geçişinin manuel olduğu eski UIKit koduyla çalışırken, açık geçiş için MainActor.run kullanabilirsiniz. Bu, tüm kod tabanını yeniden yazmadan Swift Concurrency'e aşamalı geçiş için kullanışlıdır.

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

@MainActor'ın sınırlamaları

Tüm avantajlarına rağmen, @MainActor'ın uygulama mimarisi tasarlanırken dikkate alınması gereken bir dizi sınırlaması vardır. Uygulanabilirlik sınırlarını anlamak, yanlış kullanımı önlemeye yardımcı olur.

Yoğun kullanımda performans

Tüm çağrı zinciri @MainActor ile işaretlenmişse, herhangi bir ağır iş ana iş parçacığında gerçekleştirilir ve UI donmalarına neden olur. Yalnızca UI katmanının @MainActor ile işaretlenmesi, iş mantığı ve ağ isteklerinin arka plan aktörlerinde veya küresel yürütücüde bırakılması önerilir.

Bazı API'lerle uyumsuzluk

Eski callback tabanlı API'ler (örneğin, async/await olmadan URLSession) aktör bağlamını desteklemez. Entegrasyon için CheckedContinuation ile bir sarmalayıcı gereklidir. Ayrıca @MainActor, performSelector, target-action ve UIKit'in diğer asenkron olmayan desenleriyle uyumlu değildir.

Çok iş parçacıklı hata ayıklama

@MainActor ile uygulamalarda hata ayıklarken, derleyici runtime yerine derleme zamanında birçoğunu önlediği için yarış koşullarını yeniden oluşturmak daha zordur. Ancak bu, yanlış bir güvenlik hissi yaratabilir: paylaşılan değişebilir nesnelerle (örneğin NSCache veya paylaşılan küresel değişkenler) yanlış çalışma, @MainActor ile işaretlenmemişlerse ve açık senkronizasyon olmadan kullanılıyorlarsa hala mümkündür.

@MainActor test etme

@MainActor, testlerde manuel iş parçacığı değiştirme ihtiyacını ortadan kaldırdığı için UI mantığı testini önemli ölçüde basitleştirir. Ancak, birim testleri ve UI testleri yazarken dikkate alınması gereken özellikler vardır.

MainActor ile birim testleri

XCTest'te, test ortamı otomatik olarak ana iş parçacığı yürütücüsünü ayarlar. Bir test metodu ana iş parçacığında çalıştığında, @MainActor işlevlerini çağırmak ek kurulum gerektirmez — aynı bağlamda yürütülürler. Arka plan senaryolarını test etmek için, açık öncelik ve yürütücü ile Task içinde MainActor.run kullanın ve kodun arka plandan çağrıldığında doğru çalıştığını ayrıca doğrulayın.

Yaygın bir yaklaşım, asenkron işlemlerden sonra @Published özelliklerinin doğru şekilde güncellendiğini doğrulayan @MainActor ile ViewModel testidir. Aktör bağlam mirası sayesinde, test içinde await çağırmak, ek DispatchQueue garantileri veya manuel bağlam değiştirme olmadan ana iş parçacığında yürütmeyi garanti eder ve bu da test yazmayı basitleştirir.

Yeniden düzenleme sırasında izolasyon kontrolü

Mevcut kodu Swift Concurrency'e yeniden düzenlerken, derleyici aracılığıyla @MainActor izolasyonunu kontrol edin: @MainActor bağlamından @MainActor olmayan senkron metotlara yapılan herhangi bir çağrı hata olarak işaretlenir. Bu özellik, bir projeyi kademeli olarak async/await'e taşımak için kullanılır: ViewModel katmanını @MainActor olarak işaretlersiniz ve derleyici, arka plan aktörlerine taşınması gereken tüm güvensiz çağrıları vurgular.

Mock'lama ve Aktör bağlamı

@MainActor bağımlılıkları için mock'lar oluştururken, dönüş türleriyle asenkron işlevler bildiren async metotlu protokoller kullanın. Bu, aktör izolasyonunu bozmadan ağ hizmetlerini, veritabanlarını ve diğer harici bağımlılıkları değiştirmeye olanak tanır. Derleyici, mock'ın tüm izolasyon gereksinimlerini uyguladığını doğrulayarak arka plan test iş parçacıklarından @MainActor koduna yanlışlıkla erişimi önler.

Asenkron işlemler için bekleme

@MainActor kodunu senkron olarak test ederken, asenkron işlemlerin tamamlanmasını beklemek için XCTestExpectation kullanın. Testte beklentiyi ayarlayın ve ana iş parçacığında yürütülen bir closure içinde fulfillment'ı çağırın. Test süresiz olarak takılırsa — muhtemelen ana iş parçacığında çağrı gerçekleşmiyordur ve aktör izolasyonunu kontrol etmeniz gerekir. Yürütme bağlamında hata ayıklamak için, test kodu içinde Thread.isMainThread kontrolü eklemek faydalıdır.

Sıkça Sorulan Sorular

Tüm sınıfı @MainActor ile işaretlemek gerekli mi?

Hayır, yalnızca UI'yi güncelleyen metotları işaretlemek yeterlidir. Ancak, bir sınıfın bu tür birden çok metodu varsa, tüm sınıfa @MainActor eklemek daha basittir. Bu, tüm üyelerinin ana iş parçacığında yürütülmesini garanti eder ve kod bakımını basitleştirir.

@MainActor, @globalActor'dan nasıl farklıdır?

@MainActor, ana iş parçacığına bağlı küresel bir aktörün belirli bir örneğidir. @globalActor, kendi küresel aktörlerinizi oluşturmak için bir protokoldür. Örneğin, proje mimarisi gerektiriyorsa, arka plan iş parçacığında kod yürütmek için @BackgroundActor oluşturabilirsiniz.

@MainActor async/await olmadan kullanılabilir mi?

Evet, @MainActor ile senkron işlevler de ana iş parçacığında yürütülür. Ancak, @MainActor'ın asıl değeri async/await ile ortaya çıkar; asenkron bir işlev, DispatchQueue.main aracılığıyla manuel geçiş olmadan otomatik olarak ana iş parçacığında devam eder.

Bir @MainActor görevi nasıl iptal edilir?

Task.cancel(), @MainActor görevleriyle normal görevlerle aynı şekilde çalışır. Bir @MainActor görevi Task.isCancelled'ı kontrol edebilir veya CancellationError fırlatabilir. İptal sırasında ana iş parçacığı bloke olmaz — görev, en yakın askıya alma noktasında yürütmeyi durdurur.

@MainActor arka plan iş parçacığından çağrılırsa ne olur?

Derleyici güvenliği garanti eder: bir arka plan bağlamından @MainActor işlevini çağırırsanız, derleyici hatayı işaret edecektir. Asenkron çağrılar için, çağıran kodu await ile işaretlemek yeterlidir ve yürütücü ana iş parçacığına geçecektir. Senkron çağrılar için, MainActor.run aracılığıyla açık geçiş gereklidir.

Özet

  • @MainActor — ana iş parçacığında yürütmeyi garanti eden küresel bir Swift aktörü.
  • Derleyici kontrolü bir UI güvenlik hataları sınıfını tamamen ortadan kaldırır.
  • Tam sınıf ek açıklaması tüm metotlarını otomatik olarak ana iş parçacığına yerleştirir.
  • MainActor.run — eski kod ve senkron bağlamlar için açık geçiş.
  • DispatchQueue.main'den farklı olarak, @MainActor closure oluşturmaz ve yürütücü geçişi kullanır.
  • Ağır hesaplamalar UI donmalarını önlemek için @MainActor altında yapılmamalıdır.
  • Aktör bağlam mirası asenkron çağrı zincirlerini basitleştirir ve kodu tutarlı, öngörülebilir ve UI için güvenli hale getirir.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun