web-dev-qa-db-ja.com

親View ControllerでモーダルView Controllerの削除を検出するにはどうすればよいですか?

可能性のある複製:
モーダルView Controllerとしての基になるViewControllerの関数を閉じる

私はほとんどすべてを試しました。私が試したものは次のとおりです。

-(void)viewWillAppear:(BOOL)animated
{

NSLog(@"Test");

}

-(void)viewDidAppear:(BOOL)animated
{

NSLog(@"Test");

}

-(void)viewDidLoad
{

NSLog(@"Test");

}

モーダルビューコントローラーが閉じられたときに、これらが親ビューコントローラーで機能しないのはなぜですか?これを機能させるにはどうすればよいですか?

55
objc-obsessive

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

1.ブロック

最も簡単なアプローチは、コールバック block を使用することです。これは、1人のリスナー(親View Controller)のみが解雇に関心がある場合に適しています。イベントとともにいくつかのデータを渡すこともできます。

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.委任

Delegation は、Appleが推奨するパターンです。

表示されたView Controllerの削除

提示されたView Controllerが提示されたView Controllerにデータを返す必要がある場合は、 委任 デザインパターンを使用して転送を促進します。委任により、アプリのさまざまな部分でView Controllerを簡単に再利用できます。委任では、提示されたView Controllerは、正式な プロトコル からのメソッドを実装する委任オブジェクトへの参照を保存します。結果を収集すると、提示されたView Controllerはデリゲートでこれらのメソッドを呼び出します。典型的な実装では、表示するView Controllerは、それ自体を表示する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 didDismissViewController:self];
[self dismissViewControllerAnimated:YES completion:nil];

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


3.通知

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

ただし、完了したらalwaysNSNotificationCentreから削除してください。そうしないと、割り当てを解除した後でも通知が呼び出されてクラッシュするリスクがあります。 [編集者注]

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];
}

お役に立てれば!

119
Kiran Panesar

モーダルビューは、親にそれを却下するように指示する必要があります。そうすると、親は却下を行う責任があるため、親に通知されます。

この例は、新しいプロジェクトを作成してUtility Application テンプレート。

10
Paul.s