我有层次的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, 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];