質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.19%

Swift5 xib + CustomView の dependancy injection

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 337

mogiruri

score 21

こんにちは。

dependancy injectionについて理解しようと試みています。

Storyboard を使用したインスタンス化を用いて行うDIはなんとかできたのですが、
UITableViewCell + cellのxibを使用してfunc inject()を呼ぶところでpresenterがnilとなってしまいます。

xibの扱いとDIにはまだ不慣れですので、お助けいただけると幸いです。

そもそもこれがDIになっているか不安なのですが。。。

class AppDelegate内で注入しています。

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

     // 以下、presenterを、各VCに設置したinject()にて注入
        let mainTabVC = UIStoryboard(name: "MainTab", bundle: nil).instantiateInitialViewController() as! MainTabViewController
        let userDefault = UserDefault()
        let presenter = MainTabPresenter(view: mainTabVC, udManager: userDefault)
        mainTabVC.inject(presenter: presenter, userDefaultManager: userDefault)

        let addTabVC = UIStoryboard(name: "AddTab", bundle: nil).instantiateInitialViewController() as! AddTabViewController
        let alertHandller = AlertHandller()
        let addPresenter = AddTabPresenter(view: addTabVC, mainView: mainTabVC, alertHandller: alertHandller)
        addTabVC.inject(presenter: addPresenter)

        let settingTabVC = UIStoryboard(name: "SettingTab", bundle: nil).instantiateInitialViewController() as! SettingTabViewController
        let settingPresenter = SettingTabPresenter(view: settingTabVC)
        settingTabVC.inject(presenter: settingPresenter, alertHandller: alertHandller)

        let vcs = [mainTabVC, addTabVC, settingTabVC]

        let mainTabBar = UIStoryboard(name: "MainView", bundle: nil).instantiateInitialViewController() as! MainTabBarController
        mainTabBar.setViewControllers(vcs, animated: false)

     // ここまでは問題なし。無事VC内にてpresenterにアクセス可能


        // CustomTableViewCellにはxibを使用していて、これだとView内で呼ぶpresenterがnilになる
     // ListCell.xib xibファイル
        // ListCell.swift CustomView
        let listCell = UINib(nibName: "ListCell", bundle: nil).instantiate(withOwner: nil, options: nil).first as! ListCell

        let cellPresenter = ListCellPresenter(view: mainTabVC)
        listCell.inject(presenter: cellPresenter)

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = mainTabBar
        window?.makeKeyAndVisible()

        return true
    }
}

// customTableViewCell
class ListCell: UITableViewCell {

    private let shared = Sharing.shared
    private var presenter: ListCellPresenter!

    func inject(presenter: ListCellPresenter) {
        self.presenter = presenter
    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    @IBAction func favButtonTapped(_ sender: Any) {
        let row = self.tag
        presenter.countFavIcon(rowAt: row) //このpresenterがnil
    }
}

//cellのpresenter

protocol ListCellPresenterInput {
    func countFavIcon(rowAt row: Int)
}

protocol ListCellPresenterOutput: AnyObject {
    func update()
}

final class ListCellPresenter: ListCellPresenterInput {

    private let shared = Sharing.shared
    private weak var view: ListCellPresenterOutput!

    init(view: ListCellPresenterOutput) {
        self.view = view
    }

    func countFavIcon(rowAt row: Int) {
        print("called")
        view.update()
    }
}


withOwner: nil これを withOwner: ListCell.self にもしてみましたがダメでした。

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

質問がいまいち理解できていませんので、的外れならすいません。

let listCell = UINib(nibName: "ListCell", bundle: nil).instantiate(withOwner: nil, options: nil).first as! ListCell


AppDelegateのdidFinishLaunchingWithOptionsメソッド内で生成した上記listCellはどこにも使用されず、そのまま破棄されています。

仮に、別ソースコードの func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell でListCellを生成し、injectしていないなら、そのListCellのpresenterはnilです。
AppDelegateのlistCellとは別のインスタンスですし、presenterはstaticでもありません。
Sharing.sharedがシングルトンの様なものを想定していそうですが、それとも紐付いていません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/08 22:33

    コメントありがとうございます。

    AppDelegateのdidFinishLaunchingWithOptionsメソッド内で生成した上記listCellはどこにも使用されず、そのまま破棄されています。

    そうなのですね。なんとなくわかった気がするのですが、こちらには記載していませんが、cellはcellForRowAtにてdequeueReusableCellをしようし、要素をCustomCell内にあるconfigureにて作成しています。
    ということは、ここのインスタンスを使用して cell.inject()のように呼べば良いということでしょうか?
    おっしゃる通り、Sharing.sharedはシングルトンで、presenter内の他の処理でしようすることを想定しています。

    キャンセル

  • 2019/07/10 12:21

    > ここのインスタンスを使用して cell.inject()のように呼べば良いということでしょうか?
    cellForRowAt内でpresenterが生成できるならそれで良いと思います。
    ただし、ここでMainViewをstoryboardから生成しても、画面に表示しているMainViewとは別インスタンスということに気をつけてください。
    画面表示が変わっていないならwindow?.rootViewControllerから取得できるかもしれませんが。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.19%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる