iOS:在不访问其父 ViewController 的情况下关闭和呈现 ModalViewController

Posted

技术标签:

【中文标题】iOS:在不访问其父 ViewController 的情况下关闭和呈现 ModalViewController【英文标题】:iOS: Dismissing and Presenting ModalViewController without access to its Parent ViewController 【发布时间】:2012-06-11 20:29:38 【问题描述】:

背景:我想关闭我之前展示的 modalView,并立即展示我刚刚用新信息关闭的 viewController

问题:如果没有显式指针指向以模态方式呈现第一个 ViewController 的父 ViewController,我在这方面做得并不好。我正在尝试编写这个类,它不会与以前的viewController 的代码混淆。

可能的线索:我一直在尝试几件事:

1.) 尝试访问父级 ViewController,此时我不知道该怎么做。

2.) 一旦获得对父级的访问权限,我可以简单地应用以下代码:

UIViewController* toPresentViewController = [[UIViewController alloc] init];
    [self dismissViewControllerAnimated:YES completion:^
        [parentViewControllerAccessor presentModalViewController:toPresentViewController animated:YES];
];

理论上这应该可以访问父级viewController。我对其他方法持开放态度。

假设:您无权更改父 ViewController 中的任何代码。

【问题讨论】:

【参考方案1】:

您的代码看起来应该可以工作。如果您使用的是 ios 5,则有一个名为 presentingViewControllerUIViewController 属性。

@property(nonatomic, readonly) UIViewController *presentingViewController;

因此,您可以使用此属性来获取呈现您的模态控制器的视图控制器。

注意:在 iOS 4 中,parentViewController 将设置为呈现控制器,因此如果您同时支持 iOS 4 和 5,则必须先检查操作系统版本以决定要使用哪个属性使用权。在 iOS 5 中,Apple 已修复此问题,以便 parentViewController 现在专门用于包含的视图控制器的父级(请参阅UIViewController 文档中的实现容器视图控制器部分)。 p>

编辑:关于从块内访问self.presentingViewController:当块被调用时(模式视图控制器被解除后)presentingViewController 属性可能被设置为零。请记住,块内的self.presentingViewController 在块执行时给出属性值,而不是在创建块时。为了防止这种情况发生,请执行以下操作:

UIViewController* toPresentViewController = [[UIViewController alloc] init];
UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^

    [presentingViewController presentModalViewController:toPresentViewController animated:YES];
];

这是必要的,不是因为self 已消失/解除(它被块安全地保留),而是因为它不再存在,因此它的presentingViewController 现在为零。没有必要将presentingViewController 存储在其他任何地方,局部变量很好,因为它将被块保留。

【讨论】:

如果我理解正确的话,我应该把这个代码:[parentViewControllerAccessor presentModalViewController:toPresentViewController animated:YES];改为[self.presentingViewController presentModalViewController:croppedPhotoVC animated:YES];。可悲的是,这似乎不起作用。我是不是理解有误? 这可能是由于块如何保留对象 - 它会保留 self 而不是呈现视图控制器,所以当 'self' 被解除时,此属性可能会设置为 nil。将 self.presentingViewController 设置为块外的局部变量,然后在块内使用该变量。 这与我得出的结论相同。我可能必须创建一个静态变量来保存它,这样当self 被删除时,该方法仍然有效。但这看起来更像是一种黑客行为。 您不需要将其存储在静态中,该块将为您保留一个局部变量。我已经编辑了我的答案,向您展示如何做到这一点。【参考方案2】:

您可以使用通知来完成此操作。

例如,当您希望将其关闭时,从模式视图外部触发此通知:

[[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" 
                                                    object:nil 
                                                  userInfo:nil];

然后在模态视图中处理该通知:

- (void)viewDidLoad 
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(dismissMe:)
                                                 name:@"dismissModalView" 
                                               object:nil];


- (void)dismissMe:(NSNotification)notification 
    // dismiss it here.

【讨论】:

“然后在你的模态视图中处理该通知:”我不确定这是什么意思,我明确说过,我无法触摸呈现此视图控制器的前一个视图控制器上的代码。除非,我在这里误会了什么?【参考方案3】:

ios5的解决方案:

-(void)didDismissModalView:(id)sender 

   // Dismiss the modal view controller
   int sold=0;

   if(sold==0)

      //Cash_sold.delegate = self;
      // Cash_sold.user_amount.text=[NSString stringWithFormat:@"%d",somme];

      Cash_sold = [[CashSoldview alloc] initWithNibName:@"CashSoldview" bundle:nil];
      CGRect fram1 = CGRectMake(200,20,400,400);
      Cash_sold.view.superview.frame = fram1;
      Cash_sold.view.frame=fram1;
      Cash_sold.modalTransitionStyle= UIModalTransitionStyleCoverVertical;
      Cash_sold.modalPresentationStyle=UIModalPresentationFormSheet;

      UIViewController* presentingViewController = self.parentViewController;

      [self dismissViewControllerAnimated:YES completion:^
      
         [presentingViewController presentModalViewController:Cash_sold animated:YES];
      ];     
   

【讨论】:

【参考方案4】:

试试下面的代码:

[self dismissViewControllerAnimated:NO 
                         completion:^
  // instantiate and initialize the new controller
  MyViewController *newViewController = [[MyViewController alloc] init];
  [[self presentingViewController] presentViewController:newViewController
                                                animated:NO
                                              completion:nil];
];

【讨论】:

以上是关于iOS:在不访问其父 ViewController 的情况下关闭和呈现 ModalViewController的主要内容,如果未能解决你的问题,请参考以下文章

在不创建 IBOutlets 的情况下访问 UIelements

iOS view和viewController的生命周期

如何在不使用其父级的情况下设置 SimpleXmlElement 的文本值?

iOS ViewController 的可访问性标签以表单形式呈现

ios - 无法从其他视图控制器访问数据

在 iOS 中正确访问 ViewController 中的核心数据上下文 [重复]