Exploring Swift Concurrency with Actors and Structured Concurrency

Share this post on:

Introduction:

  • Concurrency Challenges in iOS Development:
    Briefly explain the complexities of managing concurrent tasks, such as race conditions and thread management.
  • Swift Concurrency Framework:
    Introduce Swift’s modern concurrency tools introduced in Swift 5.5, designed to make concurrent code safer, simpler, and more maintainable
  • Async/Await Overview:
    Introduce async and await for managing asynchronous tasks.

Example:

func fetchData() async -> String {

    return "Data fetched!"

}

Task {

    let data = await fetchData()

    print(data) // Output: Data fetched!

}
  • Structured Concurrency:

Explain the concept of structured concurrency, where tasks have a defined hierarchy, ensuring predictable and safe execution

  • The Problem Actors Solve:
    Discuss common problems in concurrent programming, such as race conditions, and how actors provide a thread-safe solution.
  • How Actors Work:
    Define actors as reference types that isolate their state and ensure only one task can access their mutable state at a time.
  • Actor Syntax:

Example of defining and using an actor:

actor Counter {
    private var value = 0

    func increment() {
        value += 1
    }

    func getValue() -> Int {
        return value
    }
}
let counter = Counter()
Task {
    await counter.increment()
    print(await counter.getValue())  // Output: 1
}
  • Task Groups:
    Explain TaskGroup and how it enables parallel execution of multiple tasks
    while maintaining control over their lifecycle.
func fetchMultipleData() async {
    await withTaskGroup(of: String.self) { group in
        group.addTask { "First Task" }
        group.addTask { "Second Task" }
        
        for await result in group {
            print(result)
        }
    }
}
  • Child Tasks:
    Discuss how child tasks inherit the parent task’s context and can
    be automatically canceled if the parent task fails.
  • Real-World Example:
    Demonstrate how to use actors and structured concurrency together in a practical scenario, such as fetching and aggregating data from multiple APIs.
actor DataManager {
    private var data = [String]()
 
    func addData(_ newData: String) {
        data.append(newData)
    }
 
    func getData() -> [String] {
        return data
    }
}
 
func fetchDataConcurrently() async {
    let dataManager = DataManager()
    
    await withTaskGroup(of: String.self) { group in
        for i in 1...3 {
            group.addTask {
                return "Data \(i)"
            }
        }
        
        for await result in group {
            await dataManager.addData(result)
        }
    }
 
    print(await dataManager.getData())  // Output: ["Data 1", "Data 2", "Data 3"]
}
  • Global Actors:
    Introduce global actors, such as MainActor, which enforce execution on specific threads.

Example:

  • Global Actors:
    Introduce global actors, such as MainActor, which enforce execution on specific threads.

Example:

@MainActor
class ViewModel {
    var title: String = ""
}
 
let viewModel = ViewModel()
Task {
    viewModel.title = "Updated on Main Thread"
}
  • Custom Executors:
    Briefly touch on custom executors for advanced performance tuning.
  • Best Practices:
    • Use actors for shared mutable state.
    • Avoid mixing older concurrency models (like DispatchQueue) with Swift concurrency.
    • Always handle cancellations properly.
  • Limitations:
    Discuss some challenges, such as debugging async tasks or dealing
    with non-Swift legacy codebases.

Recap the benefits of using actors and structured concurrency,
emphasizing how they make concurrent programming more approachable and safer.

Author: Piyush Solanki

Piyush is a seasoned PHP Tech Lead with 10+ years of experience architecting and delivering scalable web and mobile backend solutions for global brands and fast-growing SMEs. He specializes in PHP, MySQL, CodeIgniter, WordPress, and custom API development, helping businesses modernize legacy systems and launch secure, high-performance digital products.

He collaborates closely with mobile teams building Android & iOS apps , developing RESTful APIs, cloud integrations, and secure payment systems using platforms like Stripe, AWS S3, and OTP/SMS gateways. His work extends across CMS customization, microservices-ready backend architectures, and smooth product deployments across Linux and cloud-based environments.

Piyush also has a strong understanding of modern front-end technologies such as React and TypeScript, enabling him to contribute to full-stack development workflows and advanced admin panels. With a successful delivery track record in the UK market and experience building digital products for sectors like finance, hospitality, retail, consulting, and food services, Piyush is passionate about helping SMEs scale technology teams, improve operational efficiency, and accelerate innovation through backend excellence and digital tools.

View all posts by Piyush Solanki >