---
title: TaskLocal
framework: swift
role: symbol
role_heading: Class
path: swift/tasklocal
---

# TaskLocal

Wrapper type that defines a task-local value key.

## Declaration

```swift
final class TaskLocal<Value> where Value : Sendable
```

## Overview

Overview A task-local value is a value that can be bound and read in the context of a Task. It is implicitly carried with the task, and is accessible by any child tasks it creates (such as TaskGroup or async let created tasks). Task-local declarations Task locals must be declared as static properties or global properties, like this: enum Example {     @TaskLocal     static var traceID: TraceID? }

// Global task local properties are supported since Swift 6.0: @TaskLocal var contextualNumber: Int = 12 Default values Reading a task local value when no value was bound to it results in returning its default value. For a task local declared as optional (such as e.g. TraceID?), this defaults to nil, however a different default value may be defined at declaration site of the task local, like this: enum Example {      @TaskLocal     static var traceID: TraceID = TraceID.default } The default value is returned whenever the task-local is read from a context which either: has no task available to read the value from (e.g. a synchronous function, called without any asynchronous function in its call stack), or no value was bound within the scope of the current task or any of its parent tasks. Reading task-local values Reading task local values is simple and looks the same as-if reading a normal static property: guard let traceID = Example.traceID else {   print("no trace id")   return } print(traceID) It is possible to perform task-local value reads from either asynchronous or synchronous functions. Binding task-local values Task local values cannot be set directly and must instead be bound using the scoped $traceID.withValue() { ... } operation. The value is only bound for the duration of that scope, and is available to any child tasks which are created within that scope. Detached tasks do not inherit task-local values, however tasks created using the Task { ... } initializer do inherit task-locals by copying them to the new asynchronous task, even though it is an un-structured task. Using task local values outside of tasks It is possible to bind and read task local values outside of tasks. This comes in handy within synchronous functions which are not guaranteed to be called from within a task. When binding a task-local value from outside of a task, the runtime will set a thread-local in which the same storage mechanism as used within tasks will be used. This means that you can reliably bind and read task local values without having to worry about the specific calling context, e.g.: func enter() {     Example.$traceID.withValue("1234") {         read() // always "1234", regardless if enter() was called from inside a task or not:     }     }

func read() -> String {     if let value = Self.traceID {         "\(value)"      } else {          "<no value>"     } }

// 1) Call `enter` from non-Task code //    e.g. synchronous main() or non-Task thread (e.g. a plain pthread) enter()

// 2) Call 'enter' from Task Task {      enter() } In either cases listed above, the binding and reading of the task-local value works as expected. Task local values, without tasks If a task local value is bound in a context executing outside of a task (e.g. on a plain old Thread), the task local will fall-back to managing a thread-local value for the scope of the withValue function. In other words, this task locals work as expected even if used in a context without an active swift concurrency task. Examples enum Example {     @TaskLocal     static var traceID: TraceID? }

func read() -> String {     if let value = Self.traceID {         "\(value)"      } else {          "<no value>"     } }

await Example.$traceID.withValue(1234) { // bind the value   print("traceID: \(Example.traceID)") // traceID: 1234   read() // traceID: 1234

async let id = read() // async let child task, traceID: 1234

await withTaskGroup(of: String.self) { group in        group.addTask { read() } // task group child task, traceID: 1234       return await group.next()!   }

Task { // unstructured tasks do inherit task locals by copying     read() // traceID: 1234   }

Task.detached { // detached tasks do not inherit task-local values     read() // traceID: nil   } } note: TaskLocal()

## Topics

### Initializers

- [init(wrappedValue:)](swift/tasklocal/init(wrappedvalue:).md)

### Instance Properties

- [description](swift/tasklocal/description.md)
- [projectedValue](swift/tasklocal/projectedvalue.md)
- [wrappedValue](swift/tasklocal/wrappedvalue.md)

### Instance Methods

- [get()](swift/tasklocal/get().md)
- [withValue(_:operation:file:line:)](swift/tasklocal/withvalue(_:operation:file:line:).md)
- [withValue(_:operation:isolation:file:line:)](swift/tasklocal/withvalue(_:operation:isolation:file:line:).md)

## Relationships

### Conforms To

- [CustomStringConvertible](swift/customstringconvertible.md)
- [Sendable](swift/sendable.md)
- [SendableMetatype](swift/sendablemetatype.md)

## See Also

### Task-Local Storage

- [TaskLocal()](swift/tasklocal().md)
