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)