簡體   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