DependencyKeyってなに??

DIって?
依存性の注入
依存性を外部から注入すること
Dependency Injectionの略
オブジェクトの依存関係を外部から注入するデザインパターンのこと

依存って?
あるクラスやモジュールが他のクラスなどの要素(関数とか)を使うこと
依存している先が変わってしまうと、自分のクラスの結果が変わってしまうことがある

モジュールって?
プログラムの中で機能や目的に基づいてまとめられたコードのまとまりのこと。
モジュールを使うと、コードの再利用や管理が簡単になる
GPTより、ライブラリとモジュールの違い

Dependency Key って?
依存関係を本番、テスト、プレビューで自動で切り替えてくれるツール
依存の登録や差し替えが簡単になる、変更しやすい!
previewValueを追加したら、プレビューではモックデータを使ってAPIとやり取りしない、みたいなのが実装できた

依存性の注入って?
使いたいクラスのインスタンスを自分で作るのではなく、他から渡してもらうこと
protocolを使ってると、もらう側のところは変えなくて済む

TestDependencyKeyって?
そもそもDependencyKeyはTestDependencyKeyを継承したもの。
previewValueとtestValueはどっちにでも書けそう
TestDependencyKeyだけだとruntime errorらしい

PreviewValueの値を変えたい
withDependencies: do {
//ここで置き換える
}
previewでwithDependenciesを使って依存関係の上書きができた!

実際の使い方
struct SupabaseRepositoryKey: DependencyKey {
//実際にアプリを実行して使われるもの
static var liveValue: RepositoryProtocol = APIClient()
//Previewで使われるもの
static var previewValue: RepositoryProtocol = MockAPIClient()
//testの時に使われるもの
static var testValue: RepositoryProtocol = TestAPIClient()
}
extension DependencyValues {
var repository: RepositoryProtocol {
get { self[RepositoryKey.self] }
set { self[RepositoryKey.self] = newValue }
}
}
使うReducerで宣言する
@Dependency(\.supabaseRepository) var supabaseRepository
あとはAction内で使うだけ!!
try await supabaseRepository.uploadImage(image:imageData)

mockでは
func sampleHogeHoge async throws -> [Sample] {
throw APIError.invalidURL
}
//データ取得成功した場合
#Preview("成功の場合") {
SampleView(
store: .init(
initialState: reducer.State(),
reducer: {
reducer()
}
)
)
}
//データ取得失敗した場合
#Preview("失敗の場合") {
SampleView(
store: .init(
initialState: reducer.State(),
reducer: {
reducer()
}
) {
withDependencies: do {
$0.APIClient = MockFailureAPIClient()
}
}
)
}
みたいにすると、プレビューで成功とエラー画面が両方確認もできてとても良かったです