パターン1: ダイアログ(モーダル)に値を受け渡す
MainViewController
: アプリのメイン画面を扱うViewControllerとする
ModalViewController
: メイン画面から開くモーダルを扱うViewControllerとする
メイン画面の情報をダイアログに受け渡す、例えばメイン画面で保持されているユーザー情報をダイアログに引き渡すみたいな場合。
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の逆。例えば設定ダイアログなどを開き、その設定をメイン画面に反映させる場合など。
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
に設定したフィールドやメソッドも勿論同様である。
public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
{
var modalViewController = segue.DestinationController as ModalViewController;
modalViewController.SomeLabelTextField.StringValue = "hogehoge"
// => UIコンポーネントのオブジェクト(SomeLabelTextField)の参照でエラーが発生する
}
このアクセスレベルは変更できない(はず)ので、遷移先でinternal
以上のメソッドを作成しUI操作をラップする。
internal void ChangeText(string newText)
{
SomeLabelTextField.StringValue = newText;
}
public override void PrepareForSegue(NSStoryboardSegue segue, NSObject sender)
{
var modalViewController = segue.DestinationController as ModalViewController;
modalViewController.ChangeText("hogehoge"); // ChangeTextメソッド自体はprivateじゃないので呼び出せる
}
簡単にですが、値の受け渡しについてでした。ポイントはとにかく遷移先となる画面のViewControllerオブジェクトを取得することです。それさえ出来ればどうにでもなる。
本当はパターン3として通知オブジェクトを使うものを考えていたけど、画面遷移関係ないなってのと通知についての説明含めて別でまとめた方が良いなと思ったので……またその内投稿します。
何かご指摘などありましたらコメントお願いします!
Xamarin.Mac(というかMacOSのネイティブアプリ開発事例)についての情報が国内だと中々少なく、自分も未だ手探り中なので情報提供して頂けると助かります……🙏