DEV Community

Harsh Prajapat
Harsh Prajapat

Posted on Edited on

Swift Concurrency?

1. What is Swift Concurrency?
Swift Concurrency is Apple's modern asynchronous programming model introduced in Swift 5.5.

Swift concurrency is a built-in language model that allows apps to perform multiple tasks simultaneously—such as running background calculations or fetching network data—without blocking the main user interface.

Features:

async/await
Task
TaskGroup
Actor
Structured Concurrency

Benefits:

Cleaner code
Better readability
Thread-safe programming
Less callback nesting

2. What is async?
Marks a function that can suspend execution.

func fetchUsers() async -> [User] {
    return []
}

// Call using:
let users = await fetchUsers()
Enter fullscreen mode Exit fullscreen mode

3. What is await?
await waits for an async operation to complete.

let data = await apiService.fetchData()
Enter fullscreen mode Exit fullscreen mode

It suspends the current task, not the thread.

Interview Point:

  • await does not block the thread.
  • It suspends the task.

4. Difference Between Async and Sync?

Sync

let data = service.fetchData()
print(data)
Enter fullscreen mode Exit fullscreen mode

Execution waits.

Async

let data = await service.fetchData()
Enter fullscreen mode Exit fullscreen mode

Task suspends and thread is free for other work.

5. What is a Task?
Enter fullscreen mode Exit fullscreen mode

A unit of asynchronous work.

Task {
    let users = await fetchUsers()
}
Enter fullscreen mode Exit fullscreen mode

Creates a new concurrent task.

Q: Does Task {} run on the main thread?

A: Not always. Task {} inherits the current actor context. If it's created inside a @MainActor context, it executes on the Main Actor. Otherwise, Swift Concurrency schedules it on an appropriate thread, and there is no guarantee it will run on the main thread.

Task {} inherits the current actor context. If created inside @MainActor, it runs on MainActor. Otherwise, there is no guarantee which thread executes the task.

@MainActor
class MyViewModel {
    func updateUI() {
        Task {
            print(Thread.isMainThread) // true
        }
    }
}

or

class MyViewModel {
    @MainActor
    func updateUI() {
        Task {
            print(Thread.isMainThread) // true
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

✅ Task {} inherits the @MainActor context.

The task starts on the Main Actor, so UI updates are safe.

Example:

@MainActor
func loadData() {
    Task {
        // Main Actor
        title = "Loading..."
    }
}

func fetchData() {
    Task {
        // Not guaranteed Main Thread
        let data = await api.fetch()
    }
}
Enter fullscreen mode Exit fullscreen mode

A common interview follow-up:

Task {
    print(Thread.isMainThread) // true

    let data = await api.fetch()

    print(Thread.isMainThread) // may be true or false
}
Enter fullscreen mode Exit fullscreen mode

After an await, the task is guaranteed to resume on the same actor (if actor-isolated), but not necessarily on the same physical thread. Actor ≠ Thread. This distinction is very important in Swift Concurrency interviews.

func loadData() async {
    print("fetch...")
}

Task {
    await loadData()
}
Enter fullscreen mode Exit fullscreen mode

From this code alone, we cannot determine whether it runs on the main thread.

Scenario 1: Created from MainActor

@MainActor
func buttonTapped() {

    Task {
        await loadData()
    }
}
Enter fullscreen mode Exit fullscreen mode

Here Task {} inherits @MainActor.

Top comments (0)