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

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

ただいまの
回答率

89.53%

MVP構成で画面を戻る時にpresenter -> presenterへ値を渡す方法

解決済

回答 1

投稿 編集

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

hameji

score 1280

質問させてください。

現在アプリをMVPパターンで作成しています。
NavigationControllerの下にviewControllerA -> viewControllerB
と配置しています。それぞれにpresenterを持っています。
データはpresenterが持っている状態です。

順当に次にshowでviewを表示する時はデータを普通にsegueで渡せばいいのですが、
逆に戻る時データを渡すのはどのようにするのが一般的なのでしょうか?

例えば、住所録などのアプリで、各ユーザーに勤務先会社情報を持たせる場合、
会社情報をviewControllerBで入力した場合、入力し終わり戻る時、
そのデータをpresenterから1個上の階層のpresenterに渡したいのですが、
どのように実限するべきなんでしょうか?

下の階層に渡すページはいくらでもありますが、
逆に戻る時にデータを渡す方法が解説されているページは調べてもあまりなさそうでした。

presenterB (storyboardID利用)-> veiwcontrollerA (ただのfunc)-> presenterA へ
橋渡しすればできますか???
-> 試してみましたが、できませんでした。

追伸、サンプルコードかなりアバウトに書いてて、間違ってました。修正しました。

struct AddressBook {
    let user: String
    let companyInfo: CompanyInfo?
}

strunt CompanyInfo {
    let name: String
    let address: String
    let tel: String
}

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
// ViewControllerA
import UIKit
class ViewAViewController: UIViewController {
    private let viewAPresenter = viewAPresenter()
    var addressBook: AddressBook = AddressBook(user: "田中太郎", companyInfo: nil)
}
    override func viewDidLoad() {
        self.viewAPresenter.viewA = self
    }

    override func viewWillAppear(_ animated: Bool) {
        self.viewAPresenter.viewWillAppear(data: addressBook)
    }
}
extention ViewAViewContorller: ViewDelegate {
}

// ViewAPresenter
import Foundation
class ViewAPresenter {
    weak var ViewA: AddHospitalDelegate?
    var addressBook: AddressBook!

    func viewWillAppear(data: AddressBook) {
        self.addressBook = data
        print(self.addressBook)
    }
}

// ViewADelegate
protocol ViewADelegate : class {
}

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
// ViewControllerB
import UIKit
class ViewBViewController: UIViewController {
    private let viewBPresenter = viewBPresenter()
    override func viewDidLoad() {
        self.viewBPresenter.viewB = self
    }

    override func viewWillDisappear(_ animated: Bool) {
        self.viewBPresenter.viewWillDisappear()
    }
}

extention ViewBViewContorller: ViewDelegate {
}

// ViewBPresenter
import Foundation
class ViewBPresenter {
    weak var ViewB: AddHospitalDelegate?
    var companyInfo:CompanyInfo = CompanyInfo(name: "A会社", address: "B県C市", tel: "0XX-XXX-XXXX")

    func viewWillDisappear() {
        // 下記ダメでした
        let viewAPresenter = ViewAPresenter()
        viewAPresenter.Addressbook.companyInfo = companyInfo
        // 下記もダメでした
        let viewA = self.storyboard?.instantiateViewController(withIdentifier: "viewA") as! ViewAViewController
        viewA.addressbook.companyInfo = companyInfo
    }
}

// ViewBDelegate
protocol ViewBDelegate : class {
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

MVPは判りませんが、

// 下記ダメでした
let viewAPresenter = ViewAPresenter()
// 下記もダメでした
let viewA = self.storyboard?.instantiateViewController(withIdentifier: "viewA") as! ViewAViewController

上記はどちらの方法も「新しくインスタンスを生成している」ので駄目ですね。
やりたいことは「既存のインスタンスへのアクセス」かと思います。

NavigationControllerにぶら下がっているだけであれば、
https://qiita.com/superman9387/items/e913f7edbc8ea35f1471
の方法で前のViewControllerへのインスタンスへはアクセスできます。

もしモーダルとして呼ばれた側のViewControllerであれば、presentingViewControllerプロパティから呼び出し元のViewControllerにはアクセスできます。

ViewControllerの派生クラスで、何かしらのインスタンスを取得し、プレゼンターにそのインスタンスをバケツリレーしてやれば、動作するにはするのかなと思います。
MVPとやらの設計思想にそぐうのかまでは判らないので、その辺りは詳しい方にお任せします。

#強結合が嫌なのであれば、クロージャやプロトコルを使って疎結合にする方法もあるにはあります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/11/21 15:42 編集

    takabosoftさん、ありがとうございます。
    教えていただいた方法で無事実装することができました。
    viewBPresenter -> viewBViewController -> viewAViewController -> viewAPresenterと
    バケツリレーになってしまうのは仕方がないのかなと思っています。
    時間がある時に、別の方法での実装等を再度考えてみます。

    キャンセル

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

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