0

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

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

例如,我展示了控制器 A,然后是 B,然后是 C。我将每个控制器插入到索引 0。

所以我的层次结构如下

C

一个

这是我的单身

@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

UIViewControllerCI 调用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 在枚举时发生了变异

所以我认为解雇后我失去了我的对象,也许这是我的问题。

4

2 回答 2

1

这似乎不是一个很好的使用单例。

您可以通过多种方式返回 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];

现在你所要做的就是dismissBackToA在你的 AViewController 子类中重写:

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

}

这将允许您以菊花链方式连接任意数量的模态视图控制器......泛型dismissBackToA会将链“展开”回 A。A 的覆盖方法将解除它的模态 (B)。这应该会清除链中的所有其他控制器。presentController几乎充当标准代表 - 我过度指定它以强调它与presentingViewControlleriOS5+ 中的相似性。我对非弧内存有点生疏,但我认为需要分配而不是保留。

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

更新

你也可以只传递对 A 的引用,并[self.referenceToA dismissModalViewControllerAnimated:YES]在需要时发送,但这种方式感觉更通用。

您还应该注意这一点,presentModalViewController:animated:并且dismissModalViewControllerAnimated:在 6.0 中已弃用:现在您应该使用

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

在 5.0 中引入。

它们仍然可以工作,但把它当作一个警告——你必须准备好放弃对 4.3 的支持,或者让你的代码在未来以操作系统版本为条件。

于 2013-03-26T02:51:32.463 回答
0

这不是解雇控制器的好方法。仅仅为此目的创建一个单例似乎是个坏主意。到目前为止,最简单的方法是在情节提要中使用 unwind segue 来完成,但这仅适用于我认为的 iOS 6(也许 iOS 5 也是如此)。如果您想在代码中执行此操作,那么您应该使用委托或 NSNotifications 让 A 解除 C(这也将解除 B)。此外,如果您要在代码中呈现模态视图控制器,则不应使用这种已弃用的方法,而是使用 presentViewController:animated:completion:。

编辑后:

您也可以从控制器 C 执行此操作:

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
于 2013-03-26T01:14:34.737 回答