LoginSignup
0

More than 1 year has passed since last update.

Needleを使った簡単なDIの検証

Posted at

Uberが出しているDIライブラリ「needle」を使って簡単なDIの検証をしてみました。
https://github.com/uber/needle

インストール

needleを利用するためには、コードジェネレーターとアプリに組み込むライブラリの2点のインストールが必要になります。
Carthageを使うと、双方が一気に使えるようになるので、今回Carthageを用いたインストールを行いました。
Cartfileを作成し、以下を追記します。
このタイミングでの最新バージョンがv0.17.2だったため、そのバージョンを指定しています。

github "https://github.com/uber/needle.git" ~> 0.17.2

実際試して使っていく中で、Carthageでインストールしたコードジェネレーターがうまく動作せず、コードジェネレーター側はHomebrewに切り替えたため、Homebrewを用いたインストールも行いました。

brew install needle

アプリ側ライブラリの導入

Carthageを用いた導入を行います。
上記Cartfileを作成した状態で、ターミナルから以下コマンドを実行します。

carthage update --use-xcframeworks --platform iOS

Carthage/Build/以下にNeedleFoundation.xcframeworkが作成されるので、Xcodeから導入したいターゲットのGeneral > Frameworks, Libraries, and Embedded Content 項目に移動し、上で作成されたNeedleFoundation.xcframeworkをドラッグアンドドロップします。

アプリの雛形作成

今回のケースでは、Main > Root > Home の3画面構成で、Root > Home の画面内でneedleの機能を利用してみます。
Xcodeで新規プロジェクト作成、テンプレートでiOS > Appを選択、InterfaceはStoryboardを選択したプロジェクトの初期状態から始めます。

データ用の構造体作成

今回の検証では、ユーザーを示す構造体を作成し、ユーザー名だけを保持できるようにします。

struct User {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

Root画面の作成

Root画面の作成のために、DIの構成情報を定義するComponentクラス、ViewControllerクラス、xibファイルの3点を作成します。
ComponentクラスとViewControllerクラスの実装は以下のようにします。
xibファイルはHome画面への遷移用にUIButton1点だけを配置したシンプルなViewを用意します。

import NeedleFoundation

final class RootComponent: BootstrapComponent {
    var user: User {
        shared{ User(name: "Taro") }
    }
    
    var rootViewController: RootViewController {
        return RootViewController(homeBuilder: homeBuilder)
    }
    
    var homeBuilder: HomeBuilder {
        return HomeComponent(parent: self)
    }
}
import UIKit

class RootViewController: UIViewController {
    
    private let homeBuilder: HomeBuilder
    
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    init(homeBuilder: HomeBuilder) {
        self.homeBuilder = homeBuilder
        super.init(nibName: String(describing: RootViewController.self), bundle: nil)
    }

    @IBAction private func homeButtonDidTapped() {
        present(homeBuilder.homeViewController, animated: true)
    }
}

Home画面の作成

Home画面も同様、DIの構成情報を定義するComponentクラス、ViewControllerクラス、xibファイルの3点を作成します。
ComponentクラスとViewControllerクラスの実装は以下のようにします。
xibファイルはユーザーの名前表示用にUILabel1点だけを配置したシンプルなViewを用意します。

import NeedleFoundation

protocol HomeBuilder {
    var homeViewController: HomeViewController { get }
}

protocol HomeDependency: Dependency {
    var user: User { get }
}

final class HomeComponent: Component<HomeDependency>, HomeBuilder {
    var homeViewController: HomeViewController {
        return HomeViewController(user: dependency.user)
    }
}
import UIKit

class HomeViewController: UIViewController {
    
    @IBOutlet private var nameLabel: UILabel?
    
    private let user: User
    
    required init?(coder: NSCoder) {
        fatalError()
    }
    
    init(user: User) {
        self.user = user
        super.init(nibName: String(describing: HomeViewController.self), bundle: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ユーザー名表示
        nameLabel?.text = user.name
    }

}

Main > Rootの遷移作成

プロジェクト新規作成時に作成されているMain.storyboardとViewControllerからRoot画面に繋がる遷移を作成します。
Main.storyboardにRoot遷移用のUIButtonを1点配置します。
ViewControllerの実装は以下の通りです。

import UIKit

class ViewController: UIViewController {
    
    @IBAction private func rootButtonDidTapped() {
        let rootComponent = RootComponent()
        present(rootComponent.rootViewController, animated: true)
    }
}

コードジェネレーターの実行

上記で検証に用いる構成要素が揃ったので、コードジェネレーターでDIの依存関係を解決してくれるファイルの作成を行います。
ターミナルで、プロジェクトフォルダ配下のソースコードが入ってるフォルダ(新規プロジェクト作成後、AppDelegate.swiftがある階層)に移動し以下コマンドを実行します。

needle generate NeedleGenerated.swift ./

このコマンドを実行すると、同じ階層にNeedleGenerated.swiftというファイルが作成されます。

依存関係の解決

上記で生成したNeedleGenerated.swiftをXcode上で、Add Files to "プロジェクト名"の操作を行い、利用できる状態にします。
その後、AppDelegate.swiftのapplication(_:didFinishLaunchingWithOptions:)内でregisterProviderFactories()の呼び出しを追加します。

import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        registerProviderFactories()
        return true
    }
}

アプリ実行

実行すると以下のようにHome画面でユーザー名で登録した「Taro」が表示されており、検証想定していた表示が実現できています。

実行結果

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0