ios 如何检测父视图控制器中模态视图控制器的解除?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10387039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 18:10:47  来源:igfitidea点击:

How can I detect the dismissal of a modal view controller in the parent view controller?

iphoneobjective-ciosxcodemodalviewcontroller

提问by objc-obsessive

Possible Duplicate:
Call Function in Underlying ViewController as Modal View Controller is Dismissed

可能的重复:
在底层 ViewController 中调用函数作为模态视图控制器被解除

I've tried almost everything. Here's what I've tried:

我几乎什么都试过了。这是我尝试过的:

-(void)viewWillAppear:(BOOL)animated
{

NSLog(@"Test");

}

-(void)viewDidAppear:(BOOL)animated
{

NSLog(@"Test");

}

-(void)viewDidLoad
{

NSLog(@"Test");

}

Why are none of these working in my parent view controller when the modal view controller is dismissed? How can I get this to work?

当模态视图控制器被关闭时,为什么这些在我的父视图控制器中都不起作用?我怎样才能让它发挥作用?

回答by Kiran Panesar

This answer was rewritten/expanded to explain the 3 most important approaches (@galambalazs)

这个答案被重写/扩展以解释 3 种最重要的方法(@galambalazs

1. Blocks

1. 积木

The simplest approach is using a callback block. This is good if you only have one listener(the parent view controller) interested in the dismissal. You may even pass some data with the event.

最简单的方法是使用回调block。如果您只有一个监听器(父视图控制器)对解雇感兴趣,这很好。您甚至可以随事件传递一些数据。

In MainViewController.m

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

In SecondViewController.h

SecondViewController.h

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

In SecondViewController.m

SecondViewController.m

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

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


2. Delegation

2. 委托

Delegationis the recommended pattern by Apple:

Delegation是苹果推荐的模式:

Dismissing a Presented View Controller

If the presented view controller must return data to the presenting view controller, use the delegationdesign pattern to facilitate the transfer. Delegation makes it easier to reuse view controllers in different parts of your app. With delegation, the presented view controller stores a reference to a delegate object that implements methods from a formal protocol. As it gathers results, the presented view controller calls those methods on its delegate. In a typical implementation, the presenting view controller makes itself the delegate of its presented view controller.

关闭呈现的视图控制器

如果呈现的视图控制器必须将数据返回给呈现的视图控制器,请使用委托设计模式来方便传输。代表团可以更容易地重新使用视图控制器在你的应用程序的不同部分。通过委托,呈现的视图控制器存储对实现来自正式协议的方法的委托对象的引用。当它收集结果时,呈现的视图控制器在其委托上调用这些方法。在典型的实现中,呈现视图控制器使自己成为其呈现的视图控制器的委托。

MainViewController

主视图控制器

In MainViewController.h

MainViewController.h

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

Somewhere in MainViewController.m(presenting)

MainViewController.m 中的某处(展示)

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

Somewhere else in MainViewController.m(being told about the dismissal)

MainViewController.m 中的其他地方(被告知解雇)

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

SecondViewController

第二个视图控制器

In SecondViewController.h

SecondViewController.h

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

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

Somewhere in SecondViewController.m

SecondViewController.m 中的某处

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

(note: the protocol with didDismissViewController: method could be reused throughout your app)

(注意:带有 didDismissViewController: 方法的协议可以在整个应用程序中重复使用)



3. Notifications

3. 通知

Another solution is sending an NSNotification. This is a valid approach as well, it might be easier than delegation in case you only want to notifyabout the dismissal without passing much data. But it's main use case is when you want multiple listenersfor the dismissal event (other than just the parent view controller).

另一种解决方案是发送NSNotification. 这也是一种有效的方法,如果您只想通知解雇而不传递大量数据,它可能比委托更容易。但它的主要用例是当您需要多个用于解雇事件的侦听器时(不仅仅是父视图控制器)。

But make sure to alwaysremove yourself from NSNotificationCentreafter you are done! Otherwise you risk of crashing by being called for notifications even after you are deallocated. [editor's note]

但是请确保在完成后始终将自己从NSNotificationCentre 中移除!否则,即使在您被解除分配后,您也有可能因被调用通知而崩溃。 [编者注]

In MainViewController.m

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");
}

In SecondViewController.m

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

Hope this helps!

希望这可以帮助!

回答by Paul.s

The modal view should tell its parent to dismiss it, then the parent will know because it is responsible for doing the dismissing.

模态视图应该告诉它的父级解除它,然后父级就会知道,因为它负责进行解除。

An example of this can be seen if you create a new project and choose the Utility Applicationtemplate.

如果您创建一个新项目并选择Utility Application模板,则可以看到此示例。