Slide 1

Slide 1 text

iOS͸ࣗಈੜ੒ͷເΛ ݟΔ͔ʁ 5BLFTIJ*IBSB QPUBUPUJQT

Slide 2

Slide 2 text

ࣗݾ঺հ • Takeshi Ihara • Recruit Marketing Partners • iOS Engineer • Twitter: @nonchalant0303 • GitHub: Nonchalant

Slide 3

Slide 3 text

Dependency Injection (DI)

Slide 4

Slide 4 text

DI Library • DIKit • Swinject • Typhoon • Cleanse

Slide 5

Slide 5 text

Swinject https://github.com/Swinject/Swinject • Swinject helps your app split into loosely- coupled components, which can be developed, tested and maintained more easily • Swinject is powered by the Swift generic type system and first class functions to define dependencies of your app simply and fluently

Slide 6

Slide 6 text

protocol UseCase {} struct UseCaseImpl: UseCase {} let container = Container() container.register(UseCase.self) { _ in UseCaseImpl() } let useCase = container.resolve(UseCase.self)!

Slide 7

Slide 7 text

container.register(A_UseCase.self) { r in A_UseCaseImpl(repository: r.resolve(A_Repository.self)!) } container.register(A_Repository.self) { r in A_RepositoryImpl(dataStore: r.resolve(A_DataStore.self)!) } container.register(A_DataStore.self) { _ in A_DataStoreImpl() } … container.register(Z_DataStore.self) { _ in Z_DataStoreImpl() }

Slide 8

Slide 8 text

container.register(A_UseCase.self) { r in A_UseCaseImpl(repository: r.resolve(A_Repository.self)!) } // container.register(A_Repository.self) { r in // A_RepositoryImpl(dataStore: r.resolve(A_DataStore.self)!) // } container.register(A_DataStore.self) { _ in A_DataStoreImpl() } … container.register(Z_DataStore.self) { _ in Z_DataStoreImpl() } ಈత%*ͳͷͰࢀর͞ΕΔ·Ͱؾ͚ͮͳ͍ʂ

Slide 9

Slide 9 text

Sourcery https://github.com/krzysztofzablocki/Sourcery • Sourcery is a code generator for Swift language, built on top of Apple's own SourceKit • It extends the language abstractions to allow you to generate boilerplate code automatically • It uses Stencil as template language

Slide 10

Slide 10 text

struct UseCaseDependencyInjector: DependencyInjector { func inject(container: Container) { {% for interface in types.protocols where interface.name|hasSuffix:"UseCase" %} {% for implement in types.all where implement.name|hasPrefix:interface.name %} container.register({{ interface.name }}.self) { r in {{ implement.name }}( {% for parameter in implement.initializers.first.parameters %} {{ parameter.name }}: r.resolve({{ parameter.typeName }}.self)! {% endfor %} ) } {% endfor %} {% endfor %} } }

Slide 11

Slide 11 text

// SourceryͷΠϯετʔϧ brew install sourcery // ϑΝΠϧੜ੒ sourcery \ —sources Project/UseCase \ —templates UseCase.stencil \ —output .

Slide 12

Slide 12 text

struct UseCaseDependencyInjector: DependencyInjector { func inject(container: Container) { container.register(A_UseCase.self) { _ in A_UseCaseImpl() } container.register(B_UseCase.self) { r in B_UseCaseImpl( repository: r.resolve(B_Repository.self)! ) } … container.register(Z_UseCase.self) { r in Z_UseCaseImpl( repository: r.resolve(Z_Repository.self)! ) } } }

Slide 13

Slide 13 text

Summary • ϘΠϥʔϓϨʔτίʔυ͸ΨϯΨϯࣗಈੜ੒͠Α͏ʂ • ໋໊نଇΛ͔ͳΓར༻͚ͨ͠ͲɺSourcery͸͋Δ Protocolʹద߹͍ͯ͠Δܕ͚ͩΛநग़Ͱ͖ΔͷͰ Interface, ImplementsͰPrefix͕ͣΕͯͯ΋େৎ෉ͳ͸ ͣʂ • Sourceryʹ͓͚ΔStencilͷจ๏͸ https://github.com/ SwiftGen/StencilSwiftKit ʹ͋Γ·͢ʂ