代码之家  ›  专栏  ›  技术社区  ›  Bryan

作为模式视图控制器的底层视图控制器中的调用函数被取消

  •  10
  • Bryan  · 技术社区  · 15 年前

    我有一个主视图控制器。我调用[Self-PushModalView Controller:SomeView Controller],它使SomeView Controller成为活动视图。

    现在,我想调用MainViewController中的函数,因为SomeViewController使用[Self-DismissModalView Controller]消失。

    未调用ViewDidAppear,可能是因为视图已经存在,就在模式视图的下面。当modalview解除自身时,如何调用mainviewcontroller中的函数?

    谢谢!

    3 回复  |  直到 9 年前
        1
  •  28
  •   Community Mohan Dere    9 年前

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

    1。阻碍

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

    主视图控制器.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];
    

    第二视图控制器.h

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

    第二视图控制器.m

    - (IBAction)close:(id)sender 
    {
        [self dismissViewControllerAnimated:YES completion:nil];
    
        if (self.didDismiss) 
            self.didDismiss(@"some extra data");
    }
    

    2。代表团

    Delegation 苹果推荐的模式是:

    解除显示的视图控制器

    如果呈现视图控制器必须将数据返回到呈现视图控制器,请使用 delegation 设计模式以便于传输。委派使在应用程序的不同部分重新使用视图控制器变得更容易。通过委托,呈现的视图控制器存储对委托对象的引用,该对象实现了来自 protocol . 当它收集结果时,显示的视图控制器在其委托上调用这些方法。在一个典型的实现中,呈现视图控制器使自己成为其呈现视图控制器的委托。

    主视图控制器

    主视图控制器.h

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

    在某个地方 主视图控制器.m (呈现)

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

    在别的地方 主视图控制器.m (被告知解雇)

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

    辅助视图控制器

    第二视图控制器.h

    @protocol SecondViewControllerDelegate <NSObject>
    - (void)didDismissViewController:(UIViewController*)vc;
    @end
    
    @interface SecondViewController : UIViewController
    @property (nonatomic, weak) id<SecondViewControllerDelegate> delegate;
    // ... other properties
    @end
    

    在某个地方 第二视图控制器.m

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

    (注意:使用didismissViewController:method的协议可以在整个应用程序中重用)


    三。通知

    另一个解决方案是发送 NSNotification . 这也是一个有效的方法,如果您只想这样做的话,它可能比委托更容易。 通知 关于解雇而没有传递太多数据。但它的主要用途是在你想要的时候 多个侦听器 对于解雇事件(而不仅仅是父视图控制器)。

    但一定要 总是 把你自己从 N通知中心 完成后!否则,即使在解除分配之后,仍有被调用通知的风险。 [编者按]

    主视图控制器.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");
    }
    

    第二视图控制器.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];
    }
    

    希望这有帮助!

        2
  •  3
  •   Lars Blumberg    9 年前

    使用退出(解除)segue

    当您使用故事板和段落时,您可以使用非常方便的方法,对解除模式视图控制器使用最少的代码,并通知基础视图控制器模式视图控制器已关闭。

    使用退出(展开)段,您可以获得3个优势:

    1. 您无需编写任何代码,即可解除模态视图控制器和
    2. 您可以让iOS在基础视图控制器内调用一个回调方法,该方法显示了模型视图控制器。
    3. 您使用的语义与您在实现 PrepareForSegue:中已经知道的语义完全相同

    只需两步就可以实现

    1. 在视图控制器中创建显示另一个(模式)视图控制器的操作方法:

    swift

    @ibaction func unwindfromsegue(segue:uiStoryboardsegue){
    print(“从segue展开”,segue.identifier)
    }
    

    目标-c

    —(ibAction)UnwindFromSegue:(uiStoryboardSegue*)Segue{
    nslog(@“从segue%s展开”,segue.identifier);
    }
    
    1. 在故事板中,右键单击“退出SEgue”(又称“展开SEgue”,它是视图控制器顶部的最后一个图标),拖动&dropunwindfromsegue:到按钮上,然后选择“操作”

    你完了!现在,当您单击disclose按钮和unwindfromsegue:通知基础视图控制器modal view controller has closed.

    并通知底层视图控制器模态视图控制器已关闭。

    使用退出(展开)段,您可以获得3个优势:

    1. 你不需要写任何代码关闭模态视图控制器和
    2. 您可以让iOS呼叫A基础视图控制器内的回调方法这就是模型视图控制器。
    3. 您使用的语义与从实现中已经知道的相同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(又称放卷Segue,它是视图控制器顶部的最后一个图标),拖放unwindFromSegue:到您的按钮并选择行动.

    enter image description here

    你完了!现在,当您单击dismiss按钮和从Segue展开:通知基础视图控制器模态视图控制器已关闭。

        3
  •  1
  •   Entrabiter    11 年前

    这里有一个回调解决方案,它可以减少对模式和父级的修改: 在模型的.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];
    
    推荐文章