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

时间:2010-11-11 01:24:25

标签: iphone objective-c modalviewcontroller viewdidappear

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

现在我想在mainViewController中调用一个函数,因为someViewController会随着[self dismissModalViewController]而消失。

viewDidAppear不会被调用,因为视图已经存在,就在模态视图下方。一旦modalView解散自己,如何调用mainViewController中的函数?

非常感谢!

3 个答案:

答案 0 :(得分:29)

这个答案被重写/扩展,以解释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推荐的模式:

  

取消提供的视图控制器

     

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

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

希望这有帮助!

答案 1 :(得分:3)

使用exit(展开)segue

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

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

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

    只需两步即可实施

    1. 在视图控制器中创建一个提供另一个(模态)视图控制器的操作方法:
    2. <强>夫特

      @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 (也就是展开segue,它是视图控制器顶部的最后一个图标),拖放&amp;将unwindFromSegue:放到按钮上,然后选择操作
      2. enter image description here

        你已经完成了!现在,当您单击dismiss按钮时,模态视图控制器将关闭,unwindFromSegue:会通知您的基础视图控制器模态视图控制器已关闭。

答案 2 :(得分:1)

这是一个回调解决方案,它对您的模态和父级进行较少的修改: 在模型中.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];