13

mainViewController があります。someViewController をアクティブ ビューにする [self pushModalViewController:someViewController] を呼び出します。

someViewController が [self disconnectModalViewController] で消えるので、mainViewController の関数を呼び出したいと思います。

viewDidAppear が呼び出されないのは、モーダル ビューのすぐ下にビューが既に存在していたためと考えられます。modalView が自分自身を閉じたら、mainViewController で関数を呼び出すにはどうすればよいですか?

どうもありがとう!

4

3 に答える 3

32

この回答は、3つの最も重要なアプローチを説明するために書き直され/拡張されました(@galambalazs

1. ブロック

最も簡単な方法は、 callback を使用することblockです。これは、却下に関心のあるリスナー(親ビュー コントローラー)が 1 つしかない場合に適しています。イベントでデータを渡すこともできます。

MainViewController.m

SecondViewController* svc = [[SecondViewController alloc] init];
svc.didDismiss = ^(NSString *data) {
    // this method gets called in MainVC when your SecondVC is dismissed
    NSLog(@"Dismissed SecondViewController");
};
[self presentViewController:svc animated:YES completion:nil];

SecondViewController.h

@interface MainViewController : UIViewController
    @property (nonatomic, copy) void (^didDismiss)(NSString *data);
    // ... other properties
@end

SecondViewController.m

- (IBAction)close:(id)sender 
{
    [self dismissViewControllerAnimated:YES completion:nil];

    if (self.didDismiss) 
        self.didDismiss(@"some extra data");
}

2.委任

DelegationApple が推奨するパターンは次のとおりです。

提示されたView Controllerを閉じる

提示されたビュー コントローラーが提示元のビュー コントローラーにデータを返す必要がある場合は、委任デザイン パターンを使用して転送を容易にします。委任により、アプリのさまざまな部分でビュー コントローラーを簡単に再利用できます。委任により、提示されたビュー コントローラーは、正式なプロトコルからメソッドを実装するデリゲート オブジェクトへの参照を格納します。結果を収集すると、提示されたビュー コントローラーはデリゲートでこれらのメソッドを呼び出します。典型的な実装では、表示側のビュー コントローラーは、自身を表示されたビュー コントローラーのデリゲートにします。

MainViewController

MainViewController.h

@interface MainViewController : UIViewController <SecondViewControllerDelegate>
    - (void)didDismissViewController:(UIViewController*)vc;
    // ... properties
@end

MainViewController.mのどこか(提示)

SecondViewController* svc = [[SecondViewController alloc] init];
svc.delegate = self;
[self presentViewController:svc animated:YES completion:nil];

MainViewController.m の別の場所 (解雇について通知されます)

- (void)didDismissViewController:(UIViewController*)vc
{
    // this method gets called in MainVC when your SecondVC is dismissed
    NSLog(@"Dismissed SecondViewController");
}

SecondViewController

SecondViewController.h

@protocol SecondViewControllerDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
@end

@interface SecondViewController : UIViewController
@property (nonatomic, weak) id<SecondViewControllerDelegate> delegate;
// ... other properties
@end

SecondViewController.mのどこかに

[self.delegate myActionFromViewController:self];
[self dismissViewControllerAnimated:YES completion:nil];

(注: didDismissViewController: メソッドを使用したプロトコルは、アプリ全体で再利用できます)


3. 通知

別の解決策は、NSNotification. これも有効なアプローチです。多くのデータを渡さずに解雇について通知するだけの場合は、委任よりも簡単かもしれません。ただし、主な使用例は、解雇イベントに複数のリスナーが必要な場合です(親のビューコントローラーだけではありません)。

ただし、終了後は必ずNSNotificationCentreから自分自身を削除してください。そうしないと、割り当てが解除された後でも通知が呼び出されてクラッシュする危険があります。 【編集者注】

MainViewController.m

- (IBAction)showSecondViewController:(id)sender 
{
    SecondViewController *secondVC = [[SecondViewController alloc] init];
    [self presentViewController:secondVC animated:YES completion:nil];

    // Set self to listen for the message "SecondViewControllerDismissed"
    // and run a method when this message is detected
    [[NSNotificationCenter defaultCenter] 
     addObserver:self
     selector:@selector(didDismissSecondViewController)
     name:@"SecondViewControllerDismissed"
     object:nil];
}

- (void)dealloc
{
    // simply unsubscribe from *all* notifications upon being deallocated
    [[NSNotificationCenter defaultCenter] removeObserver:self];
} 

- (void)didDismissSecondViewController 
{
    // this method gets called in MainVC when your SecondVC is dismissed
    NSLog(@"Dismissed SecondViewController");
}

SecondViewController.m

- (IBAction)close:(id)sender 
{
    [self dismissViewControllerAnimated:YES completion:nil];

    // This sends a message through the NSNotificationCenter 
    // to any listeners for "SecondViewControllerDismissed"
    [[NSNotificationCenter defaultCenter] 
     postNotificationName:@"SecondViewControllerDismissed" 
     object:nil userInfo:nil];
}

お役に立てれば!

于 2010-11-11T01:29:29.873 に答える
7

exit (巻き戻し) セグエの使用

ストーリーボードとセグエを使用している場合、最小限のコードで非常に便利なアプローチを使用して、モーダル ビュー コントローラーを閉じ、モーダル ビュー コントローラーが閉じられたことを基になるビュー コントローラーに通知できます。

exit (巻き戻し) セグエを使用すると、次の 3 つの利点があります。

  1. モーダル ビュー コントローラーを閉じるためのコードを記述する必要はありません。
  2. モデル ビュー コントローラーを提示した基礎となるビュー コントローラー内で、 iOS にコールバック メソッドを呼び出させることができます。
  3. 実装からすでに知っているのとまったく同じセマンティクスを使用しますprepareForSegue:

わずか2ステップで実装

  1. 別の (モーダル) ビュー コントローラーを提示するビュー コントローラーでアクション メソッドを作成します。

迅速

@IBAction func unwindFromSegue(segue: UIStoryboardSegue) {
    print("Unwind from segue", segue.identifier)
}

Objective-C

- (IBAction)unwindFromSegue:(UIStoryboardSegue *)segue {
    NSLog(@"Unwind from segue %s", segue.identifier);
}
  1. ストーリーボードで、子View Controllerで終了セグエ(別名セグエの巻き戻し、View Controllerの上部にある最後のアイコン)を右クリックし、ボタンにドラッグアンドドロップしてactionunwindFromSegue:を選択します。

ここに画像の説明を入力

あなたは終わった!dismissボタンをクリックするとモーダル ビュー コントローラーが閉じ、モーダル ビュー コントローラー ( Child ) が閉じたことを基になるビュー コントローラー ( ParentunwindFromSegue: ) に通知します。

于 2016-05-19T15:07:57.023 に答える