DependencyValues
전역적으로 사용할 수 있는 의존성 모음이에요.
원문: DependencyValues
개요
모음에서 특정 의존성에 접근할 때는 Dependency 프로퍼티 래퍼를 사용해요.
명확하게 정의된 범위에서 의존성을 바꾸려면 withDependencies(_:operation:)를 사용할 수 있어요.
의존성은 동기 또는 비동기 operation 범위가 유지되는 동안 바뀌어요.
참고: 일반적으로 변경된 의존성은
operation범위에서만 유지되고 escaping closure가 의존성을 캡처하면 변경 값이 전파되지 않아요. 다만DependencyValues안의 의존성 모음은@TaskLocal이기 때문에Task로operationclosure를 빠져나오면 변경 사항이 전파되는 예외가 있어요.자세한 내용은 Dependency lifetimes를 참고하세요.
DependencyValues에 의존성을 등록하려면 먼저 타입이 DependencyKey protocol을 준수하게 만들어 simulator와 기기에서 사용할 DependencyKey/liveValue를 지정하세요. Key는 private이어도 돼요.
그런 다음 key를 사용해 DependencyValues를 읽고 쓰는 computed property를 추가하세요.
이제 Dependency 프로퍼티 래퍼로 의존성에 접근할 수 있어요.
자세한 등록 방법은 Registering dependencies를 참고하세요.
값 생성하고 접근하기
init()
Dependency value instance를 만들어요. 보통 DependencyValues instance를 직접 만들지는 않아요. 직접 만들면 기본값에만 접근할 수 있기 때문이에요. 대신 Dependency 프로퍼티 래퍼를 사용할 때 라이브러리가 관리하는 instance를 사용해요.
Custom key subscript
사용자 정의 key와 연결된 dependency value에 접근해요. 일반적으로 사용자 정의 의존성을 등록하기 위해 DependencyValues에 computed property를 추가할 때 사용해요.
시스템 제공 dependency value와 같은 방식으로 withDependencies(_:operation:)에서 사용자 정의 값을 설정하고 Dependency 프로퍼티 래퍼로 읽어요.
Type subscript
Key type을 직접 사용해 dependency value를 읽고 쓸 수 있어요. 별도 key path를 만들지 않은 의존성은 @Dependency(APIClient.self)와 $0[APIClient.self] 형태로 접근해요.
값 재정의하기
withDependencies(_:operation:)
동기 또는 비동기 operation을 실행하는 동안 현재 의존성을 갱신해요. updateValuesForOperation 안에서 DependencyValues에 적용한 변경은 operation에서 실행되는 모든 코드에 보여요. 함수는 operation이 반환한 결과를 그대로 반환해요.
withDependencies(from:operation:fileID:filePath:line:column:)
특정 object에 연결된 의존성을 가져온 뒤 동기 또는 비동기 operation 동안 현재 의존성을 갱신해요. 전달한 model은 @Dependency property를 하나 이상 갖거나 다른 withDependencies operation에서 초기화되어 반환된 object여야 해요.
부모 model에서 자식 model을 만들 때 부모의 의존성을 그대로 전달하려면 이 overload를 사용하세요. 일부 값을 더 재정의할 수도 있고, 변경할 값이 없다면 update closure를 생략할 수도 있어요.
prepareDependencies(_:)
애플리케이션이 살아 있는 동안 사용할 global 의존성을 준비해요. 앱의 entry point나 Xcode Preview에서 초기 의존성을 설정할 수 있고, 앱 lifecycle에서 가능한 한 일찍 호출하는 것이 좋아요.
SwiftUI entry point에서는 App 준수의 이니셜라이저에서 호출하는 것이 적절해요.
App delegate entry point에서는 didFinishLaunchingWithOptions에서 호출할 수 있어요.
중요: 하나의 dependency key는 최대 한 번만 준비할 수 있고, 접근하기 전에 준비해야 해요. 이전에 재정의했거나 접근한 의존성을 준비하려고 하면 runtime 경고가 발생해요.
Xcode Preview에서도 사용할 수 있지만 result builder와 함께 올바르게 동작하도록 let _가 필요해요.
참고: 테스트에서
prepareDependencies(_:)를 사용하는 것도 기술적으로 가능해요.하지만
prepareDependencies(_:)는 테스트 반복 실행이나 parameterized test와 호환되지 않으므로 테스트에서는 사용하지 않는 편이 나을 수 있어요.
Escaping context
withEscapedDependencies(_:)
현재 의존성을 escaping context로 전파해요. Structured concurrency를 사용할 수 없어 escaping closure를 써야 할 때 유용해요. 의존성은 structured context나 Task에서처럼 escaping 경계를 자동으로 넘어가지 않아요.
일반적으로 의존성에 접근할 수 있는 모든 escaping 코드를 이 helper로 감싸고 escaping closure에 들어가자마자 DependencyValues.Continuation.yield(_:)를 사용해야 해요. 그렇지 않으면 escaping 코드가 잘못된 의존성을 사용할 수 있어요. 가능하다면 Swift의 structured concurrency 도구로 코드를 structured 세계에 유지하고 escaping closure 사용을 피하는 것이 좋아요.
Escaping closure 안에서 의존성을 추가로 재정의하려면 yield 밖이 아니라 안에서 바꾸세요.
Dependency value
라이브러리는 다음과 같은 제어 가능한 의존성을 기본으로 제공해요.
기본 context
live
“Live” 의존성 모음이에요. Live 의존성을 다룰 때 시작점으로 유용해요. 예를 들어 기본 test 의존성 대신 애플리케이션의 live 의존성을 실행하는 테스트를 작성할 때 전체 값을 바꿀 수 있어요.
preview
previewValue를 기본으로 읽는 “Preview” 의존성 모음이에요.
test
testValue를 기본으로 읽는 “Test” 의존성 모음이에요.
Deprecations
이전 API와 migration 안내는 공식 DependencyValues deprecations 문서를 참고하세요.