繁体   English   中英

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

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

我有一个 mainViewController。 我调用 [self pushModalViewController:someViewController] 这使 someViewController 成为活动视图。

现在我想在 mainViewController 中调用一个函数,因为 someViewController 消失了 [self deniedModalViewController]。

viewDidAppear 没有被调用,可能是因为视图已经存在,就在模态视图的下方。 一旦 modalView 自行解除,如何调用 mainViewController 中的函数?

非常感谢!

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

1. 积木

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

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 推荐的模式:

关闭呈现的视图控制器

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

主视图控制器

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

希望这可以帮助!

使用退出(展开)转场

当您使用故事板和转场时,您可以使用一种非常方便的方法以最少的代码关闭模态视图控制器并通知底层视图控制器模态视图控制器已关闭。

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

  1. 您不需要编写任何代码来关闭模态视图控制器和
  2. 您可以让 iOS呈现模型视图控制器的底层视图控制器中调用回调方法
  3. 您使用与实现prepareForSegue:已经知道的相同的语义prepareForSegue:

只需两步即可实现

  1. 视图控制器中创建一个动作方法来呈现另一个(模态)视图控制器:

迅速

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

目标-C

- (IBAction)unwindFromSegue:(UIStoryboardSegue *)segue {
    NSLog(@"Unwind from segue %s", segue.identifier);
}
  1. 在情节提要中,在子视图控制器上右键单击退出 segue (又名 unwind segue,它是视图控制器顶部的最后一个图标),将unwindFromSegue:拖放到您的按钮并选择action

在此处输入图片说明

你完成了! 现在,当您单击dismiss按钮和unwindFromSegue:时,模态视图控制器将关闭unwindFromSegue:通知您的底层视图控制器(父级)模态视图控制器(子级)已关闭。

这是一个回调解决方案,它对您的模态和父级进行较少的修改:在模型的 .h 添加:

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

在模型的 .m 中,当您关闭模态时,将其放入完成中:

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

在父视图控制器中,当您实例化模态时,请设置已解除的回调:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM