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

Bry*_*yan 11 iphone objective-c viewdidappear modalviewcontroller

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

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

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

非常感谢!

Gri*_*ess 31

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

最简单的方法是使用回调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];
Run Code Online (Sandbox Code Playgroud)

SecondViewController.h中

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

SecondViewController.m中

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

    if (self.didDismiss) 
        self.didDismiss(@"some extra data");
}
Run Code Online (Sandbox Code Playgroud)

2.代表团

Delegation 是Apple推荐的模式:

解雇呈现的视图控制器

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

MainViewController

MainViewController.h中

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

MainViewController.m中的某个地方(呈现)

SecondViewController* svc = [[SecondViewController alloc] init];
svc.delegate = self;
[self presentViewController:svc animated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)

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

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

SecondViewController

SecondViewController.h中

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

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

SecondViewController.m中的某个地方

[self.delegate myActionFromViewController:self];
[self dismissViewControllerAnimated:YES completion:nil];
Run Code Online (Sandbox Code Playgroud)

(注意:带有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");
}
Run Code Online (Sandbox Code Playgroud)

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];
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!


Lar*_*erg 7

使用退出(展开)转场

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

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

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

只需两步即可实现

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

迅速

@IBAction func unwindFromSegue(segue: UIStoryboardSegue) {
    print("Unwind from segue", segue.identifier)
}
Run Code Online (Sandbox Code Playgroud)

目标-C

- (IBAction)unwindFromSegue:(UIStoryboardSegue *)segue {
    NSLog(@"Unwind from segue %s", segue.identifier);
}
Run Code Online (Sandbox Code Playgroud)
  1. 在故事板中,在子视图控制器上右键单击退出转场(又名展开转场,它是视图控制器顶部的最后一个图标),拖放unwindFromSegue:到您的按钮并选择action

在此处输入图片说明

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