Skip to content

Commit e9e82b5

Browse files
Capture current dependencies when escaping (#11)
* Capture current dependencies when escaping * Merge with current * wip * Capture escaped dependencies and restore them without merging logic. * wip * docs * fix test Co-authored-by: Brandon Williams <[email protected]>
1 parent 0702d62 commit e9e82b5

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

Sources/Dependencies/WithDependencies.swift

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,17 +309,35 @@ public func withDependencies<Model: AnyObject, R>(
309309
/// withEscapedDependencies { dependencies in
310310
/// DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
311311
/// dependencies.yield {
312-
/// // All code in here will use dependencies at the time of
313-
/// // calling DependencyValues.escape.
312+
/// // All code in here will use dependencies at the time of calling withEscapedDependencies.
314313
/// }
315314
/// }
316315
/// }
317316
/// ```
318317
///
319318
/// As a general rule, you should surround _all_ escaping code that may access dependencies with
320-
/// this helper. Otherwise you run the risk of the escaped code using the wrong dependencies. But,
321-
/// you should also try your hardest to keep your code in the structured world using Swift's tools
322-
/// of structured concurrency, and should avoid using escaping closures.
319+
/// this helper, and you should use ``DependencyValues/Continuation/yield(_:)-42ttb`` _immediately_
320+
/// inside the escaping closure. Otherwise you run the risk of the escaped code using the wrong
321+
/// dependencies. But, you should also try your hardest to keep your code in the structured world
322+
/// using Swift's tools of structured concurrency, and should avoid using escaping closures.
323+
///
324+
/// If you need to further override dependencies in the escaped closure, do so inside the
325+
/// ``DependencyValues/Continuation/yield(_:)-42ttb`` and not outside:
326+
///
327+
/// ```swift
328+
/// withEscapedDependencies { dependencies in
329+
/// DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
330+
/// dependencies.yield {
331+
/// withDependencies {
332+
/// $0.apiClient = .mock
333+
/// } operation: {
334+
/// // All code in here will use dependencies at the time of calling
335+
/// // withEscapedDependencies except the API client will be mocked.
336+
/// }
337+
/// }
338+
/// }
339+
/// }
340+
/// ```
323341
///
324342
/// - Parameter operation: A closure that takes a ``DependencyValues/Continuation`` value for
325343
/// propagating dependencies past an escaping closure boundary.
@@ -346,13 +364,14 @@ extension DependencyValues {
346364
///
347365
/// See the docs of ``withEscapedDependencies(_:)-5xvi3`` for more information.
348366
public struct Continuation: Sendable {
349-
@Dependency(\.self) private var dependencies
367+
let dependencies = DependencyValues._current
350368

351369
/// Access the propagated dependencies in an escaping context.
352370
///
353371
/// See the docs of ``withEscapedDependencies(_:)-5xvi3`` for more information.
354372
/// - Parameter operation: A closure which will have access to the propagated dependencies.
355373
public func yield<R>(_ operation: () throws -> R) rethrows -> R {
374+
// TODO: Should `yield` be renamed to `restore`?
356375
try withDependencies {
357376
$0 = self.dependencies
358377
} operation: {

Tests/DependenciesTests/DependencyValuesTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,10 @@ final class DependencyValuesTests: XCTestCase {
396396
func doSomething(expectation: XCTestExpectation) {
397397
withEscapedDependencies { continuation in
398398
DispatchQueue.main.async {
399-
withDependencies {
400-
$0.fullDependency.value = 999
401-
} operation: {
402-
continuation.yield {
399+
continuation.yield {
400+
withDependencies {
401+
$0.fullDependency.value = 999
402+
} operation: {
403403
self.value = self.fullDependency.value
404404
expectation.fulfill()
405405
}

0 commit comments

Comments
 (0)