LoginSignup
1
0

More than 3 years have passed since last update.

Xamarin.Macにおける、画面遷移に伴う値の受け渡し

Posted at

パターン1: ダイアログ(モーダル)に値を受け渡す

MainViewController : アプリのメイン画面を扱うViewControllerとする
ModalViewController : メイン画面から開くモーダルを扱うViewControllerとする

メイン画面の情報をダイアログに受け渡す、例えばメイン画面で保持されているユーザー情報をダイアログに引き渡すみたいな場合。

MainViewController.cs
private UserInfo userInfo; // ユーザー情報を表すフィールド

// 画面遷移の前に実行されるメソッド
public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
{
    // DestinationControllerプロパティで遷移先を参照できる
    var modalViewController = segue.DestinationController as ModalViewController;
    modalViewController.userInfo = userInfo; // 受け渡し方は自由(メソッドなどを使っても良い)
}

セグエを表すオブジェクトのプロパティに、遷移先のViewControllerを表すものがあるのでそれを利用する。この時キャストを忘れないように注意。
値の受け渡しは遷移先のViewControllerに対応するフィールドを用意しておいて引き渡すでも良いし、メソッドを用意しておくのでも良い。ただしprivateメソッドだと呼び出せないのでinternalにしておくこと。

パターン2: ダイアログ(モーダル)から呼び出し元に値を渡す

パターン1の逆。例えば設定ダイアログなどを開き、その設定をメイン画面に反映させる場合など。

ModalViewController.cs
private UserSettings settings; // 設定情報を表すフィールド

// ダイアログを閉じるボタン(OKボタンなど)のクリックイベント
partial void OKButtonClicked(NSObject sender)
{
    // PresentingViewControllerプロパティで呼び出し元を参照できる
    var mainViewController = PresentingViewController as MainViewController;
    mainViewController.settings = settings; // ここも受け渡し方は自由

    // ダイアログを閉じる
    DismissController(this);
}

見た目はパターン1とほぼ同じだが、セグエを使っていない点が大きく違う。
セグエは現在の画面からダイアログやモーダルシートなどの所謂子ウィンドウを開くためのものなので、それによって開かれた画面から親ウィンドウへ情報を渡すような動作の場合、セグエではなく「OK」ボタンなどのクリックイベントに処理を記述するのが自然(だと思う)。

DismissControllerは単純にダイアログを閉じるためのメソッド
ダイアログを閉じるだけのボタンを作る場合はXcodeのFirst Responderで設定できるが、上記のように受け渡しのロジックなどを追加する場合はクリックイベントを定義する必要がある。

補足: 画面遷移に合わせてUIを操作する場合の注意点

パターン1,2に共通して言えることだが、例えば設定した内容によって画面の文言が変わる、といったように遷移先のUIを操作したい時がある。

が、UIコンポーネントのオブジェクトは基本的にprivateプロパティに設定されているので別のViewControllerからは参照できない。これは自身でprivateに設定したフィールドやメソッドも勿論同様である。

MainViewController.cs
public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
{
    var modalViewController = segue.DestinationController as ModalViewController;
    modalViewController.SomeLabelTextField.StringValue = "hogehoge"
    // => UIコンポーネントのオブジェクト(SomeLabelTextField)の参照でエラーが発生する
}

このアクセスレベルは変更できない(はず)ので、遷移先でinternal以上のメソッドを作成しUI操作をラップする。

ModalViewController.cs
internal void ChangeText(string newText)
{
    SomeLabelTextField.StringValue = newText;
}
MainViewController.cs
public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
{
    var modalViewController = segue.DestinationController as ModalViewController;
    modalViewController.ChangeText("hogehoge"); // ChangeTextメソッド自体はprivateじゃないので呼び出せる
}

簡単にですが、値の受け渡しについてでした。ポイントはとにかく遷移先となる画面のViewControllerオブジェクトを取得することです。それさえ出来ればどうにでもなる。

本当はパターン3として通知オブジェクトを使うものを考えていたけど、画面遷移関係ないなってのと通知についての説明含めて別でまとめた方が良いなと思ったので……またその内投稿します。

何かご指摘などありましたらコメントお願いします!
Xamarin.Mac(というかMacOSのネイティブアプリ開発事例)についての情報が国内だと中々少なく、自分も未だ手探り中なので情報提供して頂けると助かります……🙏

1
0
2

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
1
0