$30 off During Our Annual Pro Sale. View Details »

Xcode Previewを気軽に利用するためのDI戦略

matsuji
September 03, 2023

Xcode Previewを気軽に利用するためのDI戦略

Xcode Previewでは静的なUIだけでなく、実際にUIを操作して簡単な動作確認ができます。

Xcode Previewを本格的に使うにはDependency Injection(DI)をする必要がありますが、SwiftUIのViewへのDIはアプリのトップレベルから依存をパスする、所謂バケツリレーが必要で、実装コストが大きくなってしまいます。
一方@Environment(Object)だとバケツリレーせずにDIできますが、コンパイラの力を借りることができず、Xcode Previewへのハードルが上がります。
そこでこのトークでは、Xcode Previewのことを最優先に考え、開発者が「いつでも」「気軽に」「安全に」Xcode Previewを利用できるDI戦略を紹介します。

このトークを通じて、みなさんがもっと気軽にXcode Previewを使い倒せることを目指します。

matsuji

September 03, 2023
Tweet

More Decks by matsuji

Other Decks in Technology

Transcript

  1. View Slide

  2. Xcode Preview
    1

    View Slide

  3. 1 Xcode PreviewͰͷDIઓུͱͦͷ՝୊
    2 ண؟఺ͱղܾํ๏

    View Slide

  4. 1 Xcode PreviewͰͷDIઓུͱͦͷ՝୊
    2 ண؟఺ͱղܾํ๏

    View Slide

  5. Qiita Viewer
    QiitaͷهࣄΛݕࡧͯ͠ɺ୺຤ʹอଘ͢ΔΞϓϦ
    https://github.com/mtj0928/QiitaViewer
    4

    View Slide

  6. 5

    View Slide

  7. App
    อଘࡁΈهࣄͷҰཡ
    ΞΧ΢ϯτઃఆ
    هࣄͷݕࡧ
    هࣄͷৄࡉ
    6

    View Slide

  8. App
    อଘࡁΈهࣄͷҰཡ
    ΞΧ΢ϯτઃఆ
    هࣄͷݕࡧ
    هࣄͷৄࡉ
    6

    View Slide

  9. struct ItemListView: View {
    @StateObject let viewModel = ItemListViewModel()
    var body: some View {
    // viewModelͷitemsΛ࢖ͬͯϦετΛදࣔ͢Δ
    }
    }
    class ItemListViewModel: ObservableObject {
    @Published var items: [Item] = []
    func fetchItems() async throws {
    items = try await APIClient.share.getItems()
    }
    }
    7

    View Slide

  10. struct ItemListView: View {
    @StateObject let viewModel = ItemListViewModel()
    var body: some View {
    // viewModelͷitemsΛ࢖ͬͯϦετΛදࣔ͢Δ
    }
    }
    class ItemListViewModel: ObservableObject {
    @Published var items: [Item] = []
    func fetchItems() async throws {
    items = try await APIClient.share.getItems()
    }
    }
    ViewModelΛ
    StateObjectͰ؅ཧ
    7

    View Slide

  11. struct ItemListView: View {
    @StateObject let viewModel = ItemListViewModel()
    var body: some View {
    // viewModelͷitemsΛ࢖ͬͯϦετΛදࣔ͢Δ
    }
    }
    class ItemListViewModel: ObservableObject {
    @Published var items: [Item] = []
    func fetchItems() async throws {
    items = try await APIClient.share.getItems()
    }
    }
    ViewModelΛ
    StateObjectͰ؅ཧ
    APIܦ༝ͰitemsΛऔಘ
    7

    View Slide

  12. struct ItemListView_Previews: PreviewProvider {
    static var previews: some View {
    ItemListView()
    }
    }
    8

    View Slide

  13. Xcode PreviewΛ࢖͏্Ͱͷ໰୊఺
    // ViewModelͷதͷؔ਺
    func fetchItems() async throws {
    items = try await APIClient.share.getItems()
    }
    9

    View Slide

  14. Xcode PreviewΛ࢖͏্Ͱͷ໰୊఺
    // ViewModelͷதͷؔ਺
    func fetchItems() async throws {
    items = try await APIClient.share.getItems()
    }
    ຖճAPIͷݺͼग़͕͠૸ͬͯ͠·͏
    9

    View Slide

  15. Xcode PreviewΛ࢖͏্Ͱͷ໰୊఺
    // ViewModelͷதͷؔ਺
    func fetchItems() async throws {
    items = try await APIClient.share.getItems()
    }
    ຖճAPIͷݺͼग़͕͠૸ͬͯ͠·͏
    UIͷεςʔλεͷίϯτϩʔϧ͕Ͱ͖ͳ͍
    APIͷݺͼग़͠ʹ੒ޭͨ࣌͠ͷUI
    APIͷݺͼग़͠ʹࣦഊͨ࣌͠ͷUI
    APIΛݺͼग़͍ͯ͠ΔؒͷUI
    9

    View Slide

  16. Dependency Injection

    View Slide

  17. Initializer Injection

    View Slide

  18. protocol APIClientProtocol {
    func getItems() async throws -> [Item]
    }
    class ItemListViewModel: ObservableObject {
    @Published var items: [Item] = []
    let apiClient: APIClientProtocol
    init(apiClient: APIClientProtocol) {
    self.apiClient = apiClient
    }
    func fetchItems() async throws {
    items = try await apiClient.getItems()
    }
    }
    12

    View Slide

  19. protocol APIClientProtocol {
    func getItems() async throws -> [Item]
    }
    class ItemListViewModel: ObservableObject {
    @Published var items: [Item] = []
    let apiClient: APIClientProtocol
    init(apiClient: APIClientProtocol) {
    self.apiClient = apiClient
    }
    func fetchItems() async throws {
    items = try await apiClient.getItems()
    }
    }
    APIClient༻ʹprotocolΛఆٛ
    12

    View Slide

  20. protocol APIClientProtocol {
    func getItems() async throws -> [Item]
    }
    class ItemListViewModel: ObservableObject {
    @Published var items: [Item] = []
    let apiClient: APIClientProtocol
    init(apiClient: APIClientProtocol) {
    self.apiClient = apiClient
    }
    func fetchItems() async throws {
    items = try await apiClient.getItems()
    }
    }
    APIClient༻ʹprotocolΛఆٛ
    protocolΛinitͰࠩ͠ࠐΉ
    12

    View Slide

  21. protocol APIClientProtocol {
    func getItems() async throws -> [Item]
    }
    class ItemListViewModel: ObservableObject {
    @Published var items: [Item] = []
    let apiClient: APIClientProtocol
    init(apiClient: APIClientProtocol) {
    self.apiClient = apiClient
    }
    func fetchItems() async throws {
    items = try await apiClient.getItems()
    }
    }
    APIClient༻ʹprotocolΛఆٛ
    protocolΛinitͰࠩ͠ࠐΉ
    γϯάϧτϯͷ୅ΘΓʹ
    DI͞ΕͨAPIClinetΛ࢖͏
    12

    View Slide

  22. struct ItemListView: View {
    @StateObject let viewModel: ItemListViewModel
    var body: some View {
    // viewModelͷitemsΛ࢖ͬͯϦετΛදࣔ͢Δ
    }
    }
    13

    View Slide

  23. struct ItemListView: View {
    @StateObject let viewModel: ItemListViewModel
    var body: some View {
    // viewModelͷitemsΛ࢖ͬͯϦετΛදࣔ͢Δ
    }
    }
    ViewModelΛ֎͔Βࠩ͠ࠐΉ
    13

    View Slide

  24. private struct MockAPIClient: APIClientProtocol {
    func getItems() async throws -> [Item] {
    // ϞοΫ͍ͨ͠ॲཧΛ͜͜ʹೖΕΔ
    }
    }
    struct ItemListView_Previews: PreviewProvider {
    static var previews: some View {
    let apiClient = MockAPIClient()
    let viewModel = ItemListViewModel(apiClient: apiClient)
    ItemListView(viewModel: viewModel)
    }
    }
    14

    View Slide

  25. Initializer Injection
    Ұ൪҆શͳDIख๏
    ίϯύΠϧ࣌ʹDI͞Ε͍ͯΔ͜ͱΛอূͰ͖Δ
    ґଘͷόέπϦϨʔ͕ඞཁ
    15

    View Slide

  26. Initializer Injection
    Ұ൪҆શͳDIख๏
    ίϯύΠϧ࣌ʹDI͞Ε͍ͯΔ͜ͱΛอূͰ͖Δ
    ґଘͷόέπϦϨʔ͕ඞཁ
    15

    View Slide

  27. App
    อଘࡁΈهࣄͷҰཡ
    ΞΧ΢ϯτઃఆ
    هࣄͷݕࡧ
    هࣄͷৄࡉ
    16

    View Slide

  28. App
    อଘࡁΈهࣄͷҰཡ
    ΞΧ΢ϯτઃఆ
    هࣄͷݕࡧ
    هࣄͷৄࡉ
    APIClient͕ඞཁ
    16

    View Slide

  29. App
    อଘࡁΈهࣄͷҰཡ
    ΞΧ΢ϯτઃఆ
    هࣄͷݕࡧ
    هࣄͷৄࡉ
    APIClient͕ඞཁ
    DB͕ඞཁ
    16

    View Slide

  30. App
    อଘࡁΈهࣄͷҰཡ
    ΞΧ΢ϯτઃఆ
    هࣄͷݕࡧ
    هࣄͷৄࡉ
    APIClientͱDBΛ౉͢
    APIClient͕ඞཁ
    DB͕ඞཁ
    16

    View Slide

  31. όέπϦϨʔͷ՝୊
    ݕࡧը໘͸APIΛୟ͚ͩ͘ͳͷʹɺDBͷ৘ใ΋౉͢ඞཁ͕͋Δ
    ItemListView(
    viewModel: ItemListViewModel(apiClient: MockAPIClient()),
    db: MockDatabase()
    )
    17

    View Slide

  32. όέπϦϨʔͷ՝୊
    ݕࡧը໘͸APIΛୟ͚ͩ͘ͳͷʹɺDBͷ৘ใ΋౉͢ඞཁ͕͋Δ
    ItemListView(
    viewModel: ItemListViewModel(apiClient: MockAPIClient()),
    db: MockDatabase()
    )
    ͜Εඞཁ...ʁ
    17

    View Slide

  33. όέπϦϨʔͷ՝୊
    ݕࡧը໘͸APIΛୟ͚ͩ͘ͳͷʹɺDBͷ৘ใ΋౉͢ඞཁ͕͋Δ
    ItemListView(
    viewModel: ItemListViewModel(apiClient: MockAPIClient()),
    db: MockDatabase(),
    keychain: MockKeychain(),
    fileManager: MockFileManager(),
    userDefaults: MockUserDefaults(),
    authManager: MockAuthManager(),
    logger: MockLogger(),
    ...
    )
    17

    View Slide

  34. όέπϦϨʔͷ՝୊
    ݕࡧը໘͸APIΛୟ͚ͩ͘ͳͷʹɺDBͷ৘ใ΋౉͢ඞཁ͕͋Δ
    ItemListView(
    viewModel: ItemListViewModel(apiClient: MockAPIClient()),
    db: MockDatabase(),
    keychain: MockKeychain(),
    fileManager: MockFileManager(),
    userDefaults: MockUserDefaults(),
    authManager: MockAuthManager(),
    logger: MockLogger(),
    ...
    )
    ը໘਺͕૿͑Ε͹૿͑Δ΄ͲXcode Previewʹ౉͢ґଘ͕૿͑Δ
    17

    View Slide

  35. όέπϦϨʔͷ՝୊
    ը໘ͷ਺͕૿͑Δ΄Ͳඞཁͳґଘ͕૿͑ͯɺXcode PreviewΛ
    ؾܰʹࢼͤͳ͘ͳΔ
    18

    View Slide

  36. όέπϦϨʔͷ՝୊
    ը໘ͷ਺͕૿͑Δ΄Ͳඞཁͳґଘ͕૿͑ͯɺXcode PreviewΛ
    ؾܰʹࢼͤͳ͘ͳΔ
    ର৅ͷView͕ͲͷґଘΛ࣮ࡍʹૢ࡞͢Δͷ͔ݺͼग़͠ଆ͸Θ͔Βͳ͍
    DBΛ৮Δͷ͔ɺͦΕͱ΋APIΛୟ͘ͷ͔
    Xcode Preview࣌ʹԿΛϞοΫ͢ΔͱͲ͏൓ө͞ΕΔͷ͔ͷ೺Ѳ͕೉͘͠ͳΔ
    18

    View Slide

  37. @Environment
    @EnvironmentObject

    View Slide

  38. RootView()
    .environment(\.apiClient, APIClient())
    .environment(\.database, Database())
    struct ItemListView: View {
    @Environment(\.apiClient) var apiClient: APIClientProtocol
    }
    20

    View Slide

  39. @Environmentͷ՝୊
    1. ඞཁͳґଘ͕Θ͔Βͳ͍
    struct ItemListView_Previews: PreviewProvider {
    static var previews: some View {
    ItemListView()
    .environment(\.apiClient, MockAPIClient())
    }
    }
    21

    View Slide

  40. @Environmentͷ՝୊
    1. ඞཁͳґଘ͕Θ͔Βͳ͍
    struct ItemListView_Previews: PreviewProvider {
    static var previews: some View {
    ItemListView()
    .environment(\.apiClient, MockAPIClient())
    }
    }
    ͜ΕΛ๨Εͯ΋ίϯύΠϧΤϥʔʹͳΒͳ͍
    21

    View Slide

  41. @Environmentͷ՝୊
    2. initͰΞΫηε͕Ͱ͖ͳ͍
    struct ItemListView: View {
    @Environment(\.apiClient) var apiClient: APIClientProtocol?
    @StateObject var viewModel: ItemListViewModel
    init() {
    self.viewModel = ItemListViewModel(apiClient: apiClient)
    }
    var body: some View { ... }
    }
    22

    View Slide

  42. @Environmentͷ՝୊
    2. initͰΞΫηε͕Ͱ͖ͳ͍
    struct ItemListView: View {
    @Environment(\.apiClient) var apiClient: APIClientProtocol?
    @StateObject var viewModel: ItemListViewModel
    init() {
    self.viewModel = ItemListViewModel(apiClient: apiClient)
    }
    var body: some View { ... }
    }
    initͰEnvironmentͷ஋ʹΞΫηεͰ͖ͣ
    ViewModel͕࡞Εͳ͍
    22

    View Slide

  43. ՝୊ͷཁ໿
    Initializer Injection
    ը໘ͷ਺͕૿͑Δ΄Ͳ౉͢ґଘ͕૿͑ͯɺXcode PreviewΛࢼ͠ʹ͘͘ͳΔ
    Ͳͷґଘ͕Xcode Previewʹ࣮ࡍʹඞཁͳґଘ͔ᐆດʹͳΔ
    @Environment
    ԿΛDI͢Δ΂͖͔ɺίϯύΠϥ͸Θ͔Βͳ͍
    initͰ͸ΞΫηεͰ͖ͳ͍ͷͰɺObservableObjectΛ࡞Δʹ͸޻෉͕ඞཁ
    23

    View Slide

  44. 1 Xcode PreviewͰͷDIઓུͱͦͷ՝୊
    2 ண؟఺ͱղܾํ๏

    View Slide

  45. Xcode Previewͷؔ৺ൣғ
    Xcode Preview࣌ͷؔ৺͸ର৅ͷը໘͚ͩͰ͋Γɺଞͷը໘ʹؔ৺͸ͳ͍
    struct ItemListView: View { ... }
    struct ItemListView_Previews: PreviewProvider {
    static var previews: some View {
    ItemListView(viewModel: ...)
    }
    }
    25

    View Slide

  46. Xcode Previewͷؔ৺ൣғ
    Xcode Preview࣌ͷؔ৺͸ର৅ͷը໘͚ͩͰ͋Γɺଞͷը໘ʹؔ৺͸ͳ͍
    struct ItemListView: View { ... }
    struct ItemListView_Previews: PreviewProvider {
    static var previews: some View {
    ItemListView(viewModel: ...)
    }
    }
    ItemListViewʹ͚ͩڵຯ͕͋Γ
    ભҠઌͷը໘ʹڵຯ͸ͳ͍
    25

    View Slide

  47. App
    هࣄͷݕࡧ
    อଘࡁΈهࣄͷҰཡ
    ΞΧ΢ϯτઃఆ
    هࣄͷৄࡉ
    26

    View Slide

  48. App
    ؔ৺಺
    هࣄͷݕࡧ
    ؔ৺಺
    อଘࡁΈهࣄͷҰཡ
    ؔ৺಺
    ΞΧ΢ϯτઃఆ
    ؔ৺಺
    هࣄͷৄࡉ
    26

    View Slide

  49. App
    ؔ৺֎ ؔ৺಺
    هࣄͷݕࡧ
    ؔ৺಺
    อଘࡁΈهࣄͷҰཡ
    ؔ৺಺
    ΞΧ΢ϯτઃఆ
    ؔ৺಺
    هࣄͷৄࡉ
    ؔ৺֎
    26

    View Slide

  50. App
    ؔ৺֎ ؔ৺಺
    هࣄͷݕࡧ
    Initializer Injection
    ؔ৺಺
    อଘࡁΈهࣄͷҰཡ
    ؔ৺಺
    ΞΧ΢ϯτઃఆ
    ؔ৺಺
    هࣄͷৄࡉ
    ؔ৺֎
    26

    View Slide

  51. App
    ؔ৺֎ ؔ৺಺
    هࣄͷݕࡧ
    Initializer Injection
    ؔ৺಺
    อଘࡁΈهࣄͷҰཡ
    ؔ৺಺
    ΞΧ΢ϯτઃఆ
    ؔ৺಺
    هࣄͷৄࡉ
    ؔ৺֎
    @Environment
    26

    View Slide

  52. Dependency Provider
    27

    View Slide

  53. DependencyProvider
    1. DI͍ͨ͠ΦϒδΣΫτΛ·ͱΊͨstructΛ࡞Δ
    struct AppDependency {
    let apiClient: APIClientProtocol
    let database: DatabaseProtocol
    }
    28

    View Slide

  54. DependencyProvider
    2. AppDependencyΛEnvironmentʹ౉͢
    let dependency = AppDependency(
    apiClient: APIClient(),
    database: Database()
    )
    AppRootView()
    .environment(\.dependency, dependency)
    29

    View Slide

  55. DependencyProvider
    3. Environment͔ΒґଘΛऔΓग़͠ɺunwrap͢ΔViewΛ࡞Δ
    struct DependencyProvider: View {
    @Environment(\.dependency) var dependency: AppDependency?
    let childView: (AppDependency) -> ChildView
    var body: some View {
    if let dependency {
    childView(dependency)
    } else {
    #if DEBUG
    Text("Dependency is not set.")
    // ...
    .background(.red)
    #endif 30

    View Slide

  56. DependencyProvider
    3. Environment͔ΒґଘΛऔΓग़͠ɺunwrap͢ΔViewΛ࡞Δ
    struct DependencyProvider: View {
    @Environment(\.dependency) var dependency: AppDependency?
    let childView: (AppDependency) -> ChildView
    var body: some View {
    if let dependency {
    childView(dependency)
    } else {
    #if DEBUG
    Text("Dependency is not set.")
    // ...
    .background(.red)
    #endif
    Environment͔Β
    ґଘΛऔΓग़͢
    30

    View Slide

  57. DependencyProvider
    3. Environment͔ΒґଘΛऔΓग़͠ɺunwrap͢ΔViewΛ࡞Δ
    struct DependencyProvider: View {
    @Environment(\.dependency) var dependency: AppDependency?
    let childView: (AppDependency) -> ChildView
    var body: some View {
    if let dependency {
    childView(dependency)
    } else {
    #if DEBUG
    Text("Dependency is not set.")
    // ...
    .background(.red)
    #endif
    ChildViewΛ֎͔Βࠩ͠ࠐΉ
    30

    View Slide

  58. DependencyProvider
    3. Environment͔ΒґଘΛऔΓग़͠ɺunwrap͢ΔViewΛ࡞Δ
    struct DependencyProvider: View {
    @Environment(\.dependency) var dependency: AppDependency?
    let childView: (AppDependency) -> ChildView
    var body: some View {
    if let dependency {
    childView(dependency)
    } else {
    #if DEBUG
    Text("Dependency is not set.")
    // ...
    .background(.red)
    #endif
    ґଘ͕஫ೖ͞Ε͍ͯΕ͹
    ґଘͱڞʹChildViewΛग़͢
    30

    View Slide

  59. DependencyProvider
    3. Environment͔ΒґଘΛऔΓग़͠ɺunwrap͢ΔViewΛ࡞Δ
    struct DependencyProvider: View {
    @Environment(\.dependency) var dependency: AppDependency?
    let childView: (AppDependency) -> ChildView
    var body: some View {
    if let dependency {
    childView(dependency)
    } else {
    #if DEBUG
    Text("Dependency is not set.")
    // ...
    .background(.red)
    #endif
    }
    ґଘ͕஫ೖ͞Ε͍ͯͳ͔ͬͨΒ
    ͦͷ͜ͱΛදࣔ͢Δ
    30

    View Slide

  60. DependencyProviderͷ࢖͍ํ
    1. ֤ViewͷinitͰ͸ͦͷView͕ඞཁͳґଘ͚ͩΛએݴ͢Δ
    struct ItemListView: View {
    init(viewModel: ItemListViewModel) {
    ...
    }
    }
    31

    View Slide

  61. DependencyProviderͷ࢖͍ํ
    1. ֤ViewͷinitͰ͸ͦͷView͕ඞཁͳґଘ͚ͩΛએݴ͢Δ
    struct ItemListView: View {
    init(viewModel: ItemListViewModel) {
    ...
    }
    }
    struct ItemListView_Previews: PreviewProvider {
    static var previews: some View {
    let viewModel = ItemListViewModel(apiClient: MockAPIClient())
    ItemListView(viewModel: viewModel)
    }
    }
    31

    View Slide

  62. DependencyProviderͷ࢖͍ํ
    2. ଞͷViewΛදࣔ͢Δ࣌ɺDependency ProviderΛڬΜͰґଘΛղܾ͢Δ
    var body: some View {
    ...
    .navigationDestination(for: Item.self) { item in
    }
    }
    32

    View Slide

  63. DependencyProviderͷ࢖͍ํ
    2. ଞͷViewΛදࣔ͢Δ࣌ɺDependency ProviderΛڬΜͰґଘΛղܾ͢Δ
    var body: some View {
    ...
    .navigationDestination(for: Item.self) { item in
    DependencyProvider {
    }
    }
    }
    ·ͣDependencyProviderΛݺͿ
    32

    View Slide

  64. DependencyProviderͷ࢖͍ํ
    2. ଞͷViewΛදࣔ͢Δ࣌ɺDependency ProviderΛڬΜͰґଘΛղܾ͢Δ
    var body: some View {
    ...
    .navigationDestination(for: Item.self) { item in
    DependencyProvider { dependency in
    }
    }
    }
    ґଘ͕౉͞ΕΔ
    32

    View Slide

  65. DependencyProviderͷ࢖͍ํ
    2. ଞͷViewΛදࣔ͢Δ࣌ɺDependency ProviderΛڬΜͰґଘΛղܾ͢Δ
    var body: some View {
    ...
    .navigationDestination(for: Item.self) { item in
    DependencyProvider { dependency in
    ItemDetailView(
    item,
    database: dependency.database
    )
    }
    }
    }
    ౉͞ΕͨґଘΛ࢖ͬͯ
    Child ViewΛ࡞Δ
    32

    View Slide

  66. 33

    View Slide

  67. DependencyProviderͷԿ͕خ͍͔͠
    1. ͲͷView͔ΒͰ΋ґଘ͕औΓग़ͤΔ
    non-optionalͳ஋ͱͯ͠औΓग़ͤΔ
    struct FooView: View {
    var body: some View {
    NavigationLink("࣍ͷը໘΁") {
    DependencyProvider { dependency in
    NextView(database: dependency.database)
    }
    }
    }
    }
    34

    View Slide

  68. DependencyProviderͷԿ͕خ͍͔͠
    2. ֤View͸ඞཁͳґଘ͚ͩΛinitͰએݴͰ͖Δ
    ભҠઌͷը໘ͷͨΊͷґଘ͸ඞཁͳ͍
    Xcode PreviewΛར༻͢ΔͨΊͷඞཁे෼ͳґଘΛίϯύΠϥ͕஌ΕΔ
    ݺͼग़͠ଆ͕ͲͷΑ͏ʹґଘղܾΛ͍ͯ͠Δͷ͔஌Δඞཁ͸ͳ͍
    35

    View Slide

  69. DependencyProviderͷԿ͕خ͍͔͠
    3. EnvironmentͷઃఆΛ๨ΕΔ͜ͱ͕ͳ͍
    AppDependencyͷઃఆ͸1ճͰྑ͍
    Ծʹઃఆ͠๨Ε͍ͯͨΒࢸΔͱ͜ΖͰը໘͕ਅͬ੺ʹͳΔͷͰɺ͙͢ʹؾ෇͚Δ
    ґଘΛ௥Ճ͢Δ࣌͸ɺAppDependencyʹϓϩύςΟΛ௥Ճ͢Δ
    AppDependencyΛ࡞͍ͬͯΔՕॴͰઃఆ࿙Ε͕͋ͬͨΒίϯύΠϧΤϥʔʹͳΔ
    36

    View Slide

  70. DependencyProviderͷԿ͕خ͍͔͠
    4. DIͷํ๏͕View૚Ͱด͍ͯ͡Δ
    ϓϨθϯςʔγϣϯ૚΍ϏδωεϩδοΫ૚Ͱ͸γϯϓϧͳ
    Initializer InjectionΛҡ࣋Ͱ͖Δ
    ୯ମςετͰ͸DependencyProviderʹґଘ͢Δඞཁ͕ͳ͍
    37

    View Slide

  71. Ͱ΋͜ͷํ๏ͬͯSwiftUI͚ͩͰ͢ΑͶʁ

    View Slide

  72. iOS17͔Β͸UIKitͰ΋Ͱ͖·͢
    UITraitCollectionͰSwiftUIͷEnvironmentͱಉ༷ͷ͜ͱ͕Մೳʹʂ
    ৄ͘͠͸WWDCͷηογϣϯಈըΛࢀর͍ͯͩ͘͠͞
    https://developer.apple.com/videos/play/wwdc2023/10057/
    39

    View Slide

  73. ·ͱΊ
    Xcode PreviewΛຊ֨తʹ࢖͏ʹ͸DI͸ॏཁͳςʔϚ
    Initializer Injection΍Environment͸ͦΕͧΕ՝୊͕ଘࡏ
    ͦΕͧΕͷྑ͍ͱ͜ͲΓͳDependencyProviderΛఏҊ
    iOS17͔Β͸UIKitͰಉ༷ͷ͜ͱ͕Ͱ͖Δ͔΋...ʁ
    40

    View Slide

  74. ·ͱΊ
    Xcode PreviewΛຊ֨తʹ࢖͏ʹ͸DI͸ॏཁͳςʔϚ
    Initializer Injection΍Environment͸ͦΕͧΕ՝୊͕ଘࡏ
    ͦΕͧΕͷྑ͍ͱ͜ͲΓͳDependencyProviderΛఏҊ
    iOS17͔Β͸UIKitͰಉ༷ͷ͜ͱ͕Ͱ͖Δ͔΋...ʁ
    Ξϯέʔτ/ϑΟʔυόοΫ଴͍ͬͯ·͢ʂ
    40

    View Slide