UIViewController驳回几个控制器(ios4.3及更高版本)



我有层次的uiviewcontroller已经使用presentModalViewController方法呈现。

我有一个单例抓取所有呈现的视图控制器到一个数组。

例如,我呈现控制器A,然后是B,然后是c。我将每个控制器插入索引0。

下面是层次结构

C

B

这是我的单元素

@ 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];
}

Also got this message

NSArray在被枚举时发生了变异

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

这看起来不像是Singleton的好用法。

有很多方法可以让你回到a。你不需要构造额外的委托方法或属性,因为每个控制器都通过它的presentingViewController属性引用到前一个控制器。(我将重新表述…对于iOS5+,你可以使用内置的viewController属性presentingViewController )。为了与iOS4.3兼容,创建一个属性并把它放在你的基类@interface:

    @property (nonatomic, assign) UIViewController* presentingController;

同样在基类接口中声明一个方法:

    - (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];
}

这将允许你菊花链任意数量的模态视图控制器…通用的dismissBackToA将把链"unwind"回A。A的override方法将解散它的模态(B)。这个应该清除链中的所有其他控制器。presentController的行为就像一个标准的委托——我过度指定它是为了强调它与iOS5+中的presentingViewController的相似性。我对非弧内存有点生疏,但我认为需要分配而不是保留。

我恐怕不能100%测试,因为我手头没有iOS4.3模拟器…

更新

你也可以把a的引用一直传递到链上,并在你需要的时候发送[self.referenceToA dismissModalViewControllerAnimated:YES],但这种方式感觉有点通用。

你也应该注意presentModalViewController:animated:dismissModalViewControllerAnimated:在6.0中被弃用:现在你应该使用

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

它们仍然可以工作,但把它作为一个警告-你将不得不准备放弃对4.3的支持,或者使你的代码在未来的操作系统版本上有条件

这不是一个解散控制器的好方法。仅仅为了这个目的而创建单例似乎是个坏主意。到目前为止,最简单的方法是在故事板中使用unwind segue,但我想这只适用于ios6(也许ios5也适用)如果你想在代码中做,那么你应该使用委托或NSNotifications让A解散C(它也会解散B)。此外,如果你要在代码中呈现模态视图控制器,你不应该使用这个折旧方法,使用presentViewController:animated:completion:

编辑后

:

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

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

最新更新