简体   繁体   English

在底层 ViewController 中调用函数作为模态视图控制器被解除

[英]Call Function in Underlying ViewController as Modal View Controller is Dismissed

I have a mainViewController.我有一个 mainViewController。 I call [self pushModalViewController:someViewController] which makes someViewController the active view.我调用 [self pushModalViewController:someViewController] 这使 someViewController 成为活动视图。

Now I want to call a function in mainViewController as someViewController disappears with [self dismissModalViewController].现在我想在 mainViewController 中调用一个函数,因为 someViewController 消失了 [self deniedModalViewController]。

viewDidAppear does not get called probably because the view was already there, just beneath the modal view. viewDidAppear 没有被调用,可能是因为视图已经存在,就在模态视图的下方。 How does one go about calling a function in the mainViewController once the modalView dismisses itself?一旦 modalView 自行解除,如何调用 mainViewController 中的函数?

Thanks a lot!非常感谢!

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 .最简单的方法是使用回调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.您甚至可以随事件传递一些数据。

In MainViewController.mMainViewController.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.hSecondViewController.h

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

In SecondViewController.mSecondViewController.m

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

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

2. Delegation 2. 委托

Delegation is the recommended pattern by Apple: Delegation是 Apple 推荐的模式:

Dismissing a Presented View Controller关闭呈现的视图控制器

If the presented view controller must return data to the presenting view controller, use the delegation design 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.hMainViewController.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.hSecondViewController.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 myActionFromViewController: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 .另一种解决方案是发送NSNotification This is a valid approach as well, it might be easier than delegation in case you only want to notify about the dismissal without passing much data.这也是一种有效的方法,如果您只想通知解雇而不传递大量数据,它可能比委托更容易。 But it's main use case is when you want multiple listeners for the dismissal event (other than just the parent view controller).但它的主要用例是当您需要多个用于解雇事件的侦听器时(不仅仅是父视图控制器)。

But make sure to always remove yourself from NSNotificationCentre after you are done!但是请确保在完成后始终将自己从NSNotificationCentre 中移除! Otherwise you risk of crashing by being called for notifications even after you are deallocated.否则,即使在您被解除分配后,您也可能因被调用通知而导致崩溃。 [editor's note] [编者注]

In MainViewController.mMainViewController.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.mSecondViewController.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!希望这可以帮助!

Using exit (unwind) segue使用退出(展开)转场

When you're using storyboards and segues you can use a very handy approach with minimal code to dismiss a modal view controller and inform the underlying view controller that the modal view controller has been closed.当您使用故事板和转场时,您可以使用一种非常方便的方法以最少的代码关闭模态视图控制器并通知底层视图控制器模态视图控制器已关闭。

Using exit (unwind) segues you gain 3 advantages:使用 exit (unwind) segues 可以获得 3 个优势:

  1. you don't need to write any code to dismiss the modal view controller and您不需要编写任何代码来关闭模态视图控制器和
  2. you can have iOS call a callback method inside the underlying view controller that has presented the model view controller.您可以让 iOS呈现模型视图控制器的底层视图控制器中调用回调方法
  3. you use the very same semantics that you already know from implementing prepareForSegue:您使用与实现prepareForSegue:已经知道的相同的语义prepareForSegue:

Implement it with only 2 steps只需两步即可实现

  1. Create an action method in the Parent view controller that presents another (modal) view controller:视图控制器中创建一个动作方法来呈现另一个(模态)视图控制器:

Swift迅速

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

Objective-C目标-C

- (IBAction)unwindFromSegue:(UIStoryboardSegue *)segue {
    NSLog(@"Unwind from segue %s", segue.identifier);
}
  1. In the storyboard, On child view controller right click the exit segue (aka unwind segue, it's the last of the icons at the top of your view controller), drag & drop unwindFromSegue: to your button and select action .在情节提要中,在子视图控制器上右键单击退出 segue (又名 unwind segue,它是视图控制器顶部的最后一个图标),将unwindFromSegue:拖放到您的按钮并选择action

在此处输入图片说明

You're done!你完成了! Now the modal view controller closes when you click the dismiss button and unwindFromSegue: informs your underlying view controller( Parent ) that the modal view controller( Child ) has closed.现在,当您单击dismiss按钮和unwindFromSegue:时,模态视图控制器将关闭unwindFromSegue:通知您的底层视图控制器(父级)模态视图控制器(子级)已关闭。

Here's a callback solution which takes less modifications to your modal and parent: In the Model's .h add:这是一个回调解决方案,它对您的模态和父级进行较少的修改:在模型的 .h 添加:

@property (nonatomic, copy) void (^dismissed)();

In the Model's .m put this in the completion when you dismiss the modal:在模型的 .m 中,当您关闭模态时,将其放入完成中:

 [self dismissViewControllerAnimated:YES completion:^{
    if(self.dismissed)
        self.dismissed();
}];

In the parent view controller when you instantiate your modal set the dismissed callback:在父视图控制器中,当您实例化模态时,请设置已解除的回调:

Modal = //Init your modal
[Modal setDismissed:^{
   //do stuff you wanted when it's dimissed
}];
 [self presentViewController:Modal animated:YES completion:nil];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Modal View控制器在出现内存警告时被解雇? - Modal View controller dismissed on memory warning? iPhone Modal View Controller在ViewController中单独存在 - iPhone Modal View Controller seperate in ViewController 当前模态视图控制器 - 与呈现viewcontroller交互 - Present modal view controller - interact with presenting viewcontroller 关闭控制器后如何在另一个视图中调用方法 - How to call a method in another view when controller is dismissed 当关闭模态视图控制器时,底层的UIScrollView会调整为全屏大小 - When Dismissing a Modal View Controller the underlying UIScrollView resizes to fullscreen 父视图 controller 中是否有在模态视图被关闭后被调用的委托? - Is there a delegate in the parent view controller that gets called after a modal view gets dismissed? 在加载另一个ViewController时呈现模态视图控制器 - Presenting a modal view controller when loading another ViewController 仅在解雇了另一个视图控制器之后,再显示一个模态视图控制器 - Presenting a modal view controller only after another one has been dismissed multi viewcontroller:从子视图控制器调用根控制器的变量 - multi viewcontroller : call variable of root controller from a sub view controller 从另一个模态视图控制器调用时ABPeoplePicker崩溃,并且两者均被消除 - Crash in ABPeoplePicker when called from another modal viewcontroller and both dismissed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM