AsyncLazy is a lightweight Swift concurrency utility for lazily initializing and caching values in a thread-safe manner. It only computes the value upon first request, and all subsequent requests await that same result. This design eliminates redundant calculations and simplifies concurrent workflows.
- Actor-based – Ensures thread safety without manual locks or complicated synchronization.
- Single Initialization – Guarantees only one invocation of the factory closure, even under heavy concurrency.
- Flexible – Optional convenience APIs like
mapanduponInitiationlet you transform or observe values after creation. - Performance-Focused – Minimal overhead; only lock-free concurrency operations via Swift actors.
- Swift 6.0 or later.
- Works on iOS 13+, macOS 10.15+, tvOS 13+, watchOS 6+, visionOS 1+ (or matching Swift concurrency back-deployment targets).
dependencies: [
.package(url: "https://github.com/arihe/AsyncLazy.git", from: "1.0.0")
]Then add AsyncLazy as a dependency in your target:
.target(name: "YourAppOrLibrary", dependencies: [
.product(name: "AsyncLazy", package: "AsyncLazy")
])-
Create an
AsyncLazywith a factory closure that provides the value:let lazyValue = AsyncLazy { // Simulate a slow operation try? await Task.sleep(nanoseconds: 300_000_000) return "Hello, AsyncLazy!" }
-
Retrieve the value – The first time you call
.value, it triggers the factory. All subsequent calls wait on that same result:Task { let val = await lazyValue.value print(val) // Prints: Hello, AsyncLazy! }
-
Check if initiated –
isInitiatedtells you if the value has already been created:if await lazyValue.isInitiated { print("Value was already created.") } else { print("Still uninitiated.") }
-
Perform tasks upon initialization – Want to run some async work once the value is ready? Use
uponInitiation:lazyValue.uponInitiation(task: .init(work: { val in print("Value is now ready: \(val)") }, priority: nil))
-
Transform with
map– Create a newAsyncLazyderived from the original:let mapped = await lazyValue.map { str in "Mapped: \(str.uppercased())" } initializationTask: nil let mappedVal = await mapped.value // => "Mapped: HELLO, ASYNCLAZY!"
This package includes a robust suite of Swift tests (using XCTest or SwiftTest) covering:
- Basic initialization and access
- Concurrency scenarios
- Stress tests under high load
- Verification of single-invocation guarantees
Simply open the project in Xcode and run the tests (⌘U), or from the command line:
swift testThis project is released under the MIT License.
© 2025 Ari He. All rights reserved.
Contributions are welcome! If you find a bug or have a feature request:
- Open an issue.
- Or fork, make changes, and submit a pull request.