UIViewController解雇几个控制器(iOS 4.3及更高版本)

时间:2013-03-26 00:58:06

标签: ios uiviewcontroller presentmodalviewcontroller

我有使用presentModalViewController方法呈现的UIViewControllers层次结构。

我有单例,可以将所有呈现的视图控制器都抓取到数组中。

例如,我提出了控制器A,然后是B,然后是C.我将每个控制器插入索引0。

所以我的层次结构如下

C

A

这是我的单身人士

@implementation PresentHelper

- (id)init
{
    self = [super init];
    if (self) {
        self.viewControllers = [NSMutableArray new];
    }
    return self;
}

+ (PresentHelper *)sharedInstance
{
    static dispatch_once_t pred;
    static PresentHelper *sharedInstance = nil;
    dispatch_once(&pred, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (void)backToViewControllerA
{
    for (UIViewController *controller in self.viewControllers) {
        [controller dismissModalViewControllerAnimated:NO];
    }
    [self.viewControllers removeAllObjects];
}

@end

UIViewController C中,我调用backToViewControllerA方法。

因此,当我调试此方法时,我想知道为什么- viewDidLoad方法(对于self.viewControllers中的每个控制器)在此行[controller dismissModalViewControllerAnimated:NO];之后调用,因为我认为它不应该像这样工作,但它的工作原理。

所以,也许这不是返回视图控制器A的一种方式,但我的问题在任何情况下都与viewDidLoad方法有关。

这也是我下面的代码我如何呈现每个控制器。我有基类,每个(A,B,C控制器都是从它继承而来)。

- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
{
    PresentHelper *presentHelper = [PresentHelper sharedInstance];
    [presentHelper.viewControllers insertObject:modalViewController atIndex:0];
    [super presentModalViewController:modalViewController animated:animated];
}

也得到了这条消息

NSArray在被枚举时被突变

因此我认为在解雇后我失去了我的对象,也许这就是我的问题。

2 个答案:

答案 0 :(得分:1)

这似乎不是一个单身人士的好用。

有许多方法可以回到A.您不需要构建额外的委托方法或属性,因为每个控制器都通过它的presentingViewController属性引用前一个。 (我将重新说明......对于iOS5 +,您可以使用内置的viewController属性presentingViewController )。要与iOS4.3保持兼容,请创建一个属性并将其放在基类@interface中:

    @property (nonatomic, assign) UIViewController* presentingController;

同样在您的base clase界面中,声明一个方法:

    - (void) dismissBackToA;

@implementation@synthesize您的媒体资源中定义dismissBackToA

 - (void) dismissBackToA
{
    if ([[self presentingController] respondsToSelector:@selector(dismissBackToA)]) {
           [[self presentingController] performSelector:@selector(dismissBackToA)];
    }
}

在你的模态现有代码中,在所呈现的VC中设置对self的引用 - 例如:

   MasterViewController* BViewController = [[BViewController alloc] init];
   BViewController.presentingController = self;
   [self presentModalViewController:BViewController animated:YES];

现在你所要做的就是覆盖AViewController子类中的dismissBackToA

- (void) dismissBackToA
{
    [self dismissModalViewControllerAnimated:YES];

}

这将允许您菊花链式连接任意数量的模态viewControllers ...通用dismissBackToA将'展开'链回到A. A的覆盖方法将忽略它的模态(B)。这个应该消灭链中的所有其他控制器。 presentController几乎是一个标准代表 - 我已经过度指定它以强调它与iOS5 +中presentingViewController的相似性。我在nonArc内存上有点生疏,但我认为需要分配不保留。

我恐怕无法测试这100%,因为我手头没有iOS4.3模拟器......

更新

您也可以直接将链接传递给A并在需要时发送[self.referenceToA dismissModalViewControllerAnimated:YES],但这种方式会更加通用。

您还应该注意presentModalViewController:animated:dismissModalViewControllerAnimated:在6.0中已弃用:现在您应该使用

- presentViewController:animated:completion: 
- dismissViewControllerAnimated:completion:

在5.0中引入。

它们仍然可以工作,但是将其视为警告 - 您将不得不准备放弃对4.3的支持,或者让您的代码在未来以OS版本为条件。

答案 1 :(得分:0)

这不是解雇控制器的好方法。为此目的创建单例似乎是一个坏主意。到目前为止最简单的方法是使用展开segue在故事板中进行,但这只适用于iOS 6我认为(也可能是iOS 5)。如果你想在代码中这样做,那么你应该使用委托或NSNotifications让A解雇C(这也将解雇B)。此外,如果您要在代码中呈现模态视图控制器,则不应使用此折旧方法,请使用presentViewController:animated:completion:而不是。

编辑后:

你也可以从控制器C这样做:

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];