# Understanding @MainActor and Protocols in Swift

How to manage main thread operations for UI updates effectively

- **Source:** [Swift by Sundell (swiftbysundell.com)](https://brifing.si/source/766ea933-99cd-4e7d-ac46-9e01757bf61e)
- **Published:** 2026-07-31
- **Topic:** [Software & Engineering](https://brifing.si/c/engineering)
- **Original article:** <https://www.swiftbysundell.com/articles/swift-protocols-and-the-main-actor>
- **On Brifing:** https://brifing.si/s/8b0c5884-06cc-426b-be65-f3ff8a36e294

## Core Functionality of Main Actor

The @MainActor attribute in Swift associates a type, function, or value with the global main actor, ensuring thread safety for UI updates. This is crucial for interface operations performed with UIKit or SwiftUI, as they must execute on the main thread. The mechanism prevents race conditions in multi-threaded environments, making it essential for responsive user interfaces.

## Protocol Conformance with Main Actor

When a Swift protocol is marked with @MainActor, all its members become main actor isolated. For instance, ErrorPresenter's functions using UIView require this attribute. However, this forces all conforming types to become main actor isolated, which might lead to unexpected behavior in some implementations. Careful consideration is needed when designing such protocols.

## Surprising Effects on Class Conformance

Classes conforming to a @MainActor protocol inherit this isolation completely. If Navigator class directly adopts ErrorPresenter, the entire class becomes main actor isolated. However, when using extensions, only the protocol methods remain isolated. This subtle distinction becomes crucial when optimizing for performance in complex applications.

## The Actor Type Conundrum

Custom actors like ExportService cannot conform to main actor-isolated protocols due to Swift's limitations - a type can't be both a custom actor and main actor isolated simultaneously. This reveals important threading constraints in the language that developers must account for in their architecture decisions.

## Function-Level Isolation Solution

Marking individual functions with @MainActor instead of the entire protocol provides more flexibility. UI-related functions in ErrorPresenter can be isolated while leaving other members free. This approach allows actors like ExportService to adopt the protocol without compiler errors, offering better design possibilities.

## Mixed Isolation Scenarios

The granular approach enables mixing isolated and non-isolated functions within the same protocol. While presentation functions need main thread safety, methods like shouldPresentError can remain non-isolated when they don't involve UI. This flexibility helps balance between thread safety and performance optimization.

## Limitations of Nonisolated Functions

Functions marked as nonisolated in actors cannot access the actor's state. When shouldPresentError in ErrorPresenter is nonisolated, it loses access to ExportService's properties. Developers must either modify the function's logic or implement thread-safe alternatives to work around this limitation.

## Best Practice Recommendations

While @MainActor is mandatory for UI operations, it should be applied at function level rather than protocol level. Protocols should be designed as thread-agnostic when possible, with only specific functions requiring isolation. This approach ensures compatibility with both custom actors and regular classes while maintaining thread safety where needed.

## Sources covering this story

- https://www.swiftbysundell.com/articles/swift-protocols-and-the-main-actor — 

---

_Summary written by Brifing from the original reporting. Copyright in the original article belongs to its publisher; read the full piece at the link above._
