显示为模态的两个导航控制器上的警告

Posted

技术标签:

【中文标题】显示为模态的两个导航控制器上的警告【英文标题】:Warning on two navigation controller which presented as modal 【发布时间】:2013-02-18 09:02:01 【问题描述】:

我创建了两个UIViewControll,以模态形式呈现。假设前 5 次尝试,模态将正常显示,但之后它会给我一个:

Warning: Attempt to dismiss from view controller <UINavigationController: 0x76a8450> while a presentation or dismiss is in progress!

以下是关闭当前视图控制器并呈现另一个视图控制器的代码

[customAlertLoad dismissViewControllerAnimated:NO completion:^ 
     CustomAlertMsg *cust = [[CustomAlertMsg alloc] init];
     cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
     cust.modalPresentationStyle = UIModalPresentationFormSheet;
     cust.delegate = self;

     [self.navigationController presentModalViewController:cust animated:YES];
     cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
     cust.view.superview.center = self.view.center;
];

任何帮助将不胜感激。

【问题讨论】:

视图控制器的isBeingPresentedisBeingDismissed 属性在完成块中有什么建议? 我尝试测试 isBeingDismissed 但结果始终为 NO,因此仍然显示警告。 你查过UINavigationController: 0x76a8450是哪个VC? customAlertLoadcust? 哦它的导航控制器 我想知道你是如何展示 customAlertLoad 的。 【参考方案1】:

编辑

我只记得几周前的另一个类似问题。您遇到了一种竞争状况,这可能可以使用GCD(Grand Central Dispatch)来解决。这类似于@rakeshNS 建议的解决方案,但危险性较小。 (使用计时器来处理竞争条件是不好的做法,尽管在许多语言中调用具有 0 秒计时器等待时间的方法是一种用于将该方法调用放在调用堆栈末尾的技巧,也就是使其异步)。苹果为此提供了一种机制。

我会尝试做这个轻微的修改:

[customAlertLoad dismissViewControllerAnimated:NO completion:^ 
                             dispatch_async(dispatch_get_main_queue(), ^(void) 
                                  CustomAlertMsg *cust = [[CustomAlertMsg alloc] init];
                                  cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
                                  cust.modalPresentationStyle = UIModalPresentationFormSheet;
                                  cust.delegate = self;

                                  [self.navigationController presentModalViewController:cust animated:YES];
                                  cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
                                  cust.view.superview.center = self.view.center;
                                 );
                         ];

对 dispatch_async 的调用将块放在执行堆栈的末尾。在模式被解除之前,它无法运行。这也允许在两个模态的解除和呈现上制作动画。

然而,我应该提到,在这个特定的问题中,这是一个 hack。 您在其他地方遇到了问题。如果我在测试项目中重现您的设置,我可以从完成块中创建/关闭任意数量的模式,而不会遇到您的错误(只要从用于关闭模式的自定义委托回调中调用解除代码,就像苹果建议的那样)。我会查看您的自定义警报加载和自定义警报类代码​​。

结束编辑

这可能与您的问题不同,在将代码库移动到 ARC 后,我曾遇到过弹出框的问题。在我的 Popover 发布得太早或保留时间过长的情况下发生了奇怪的事情。解决方案是创建一个实例变量来保存 Popover,并手动管理它。然后一切都开始工作了。

所以我会这样做:

@interface YourClass:UIViewController

@property (nonatomic,strong) CustomAlertMsg *cust;

@end


@implementation YourClass

... Codey Code....

-(void)pushView
     // For the sake of sanity, nil the modal here
     if(self.cust != nil) self.cust = nil;
     self.cust = [[CustomAlertMsg alloc] init];
     self.cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
     self.cust.modalPresentationStyle = UIModalPresentationFormSheet;
     self.cust.delegate = self;

     [self.navigationController presentModalViewController:self.cust animated:YES];
     self.cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
     self.cust.view.superview.center = self.view.center;


// Then where you dismiss it, or in the delegate callback that is 
//  called when you dismiss it, if you are using one anyway, 
//  nil it out
- (void)methodThatDismissesModal

     [self dismissModalViewControllerAnimated:YES];
     // This is pretty important
     if(self.cust != nil) self.cust = nil; 


... Codey Code....

@end

【讨论】:

【参考方案2】:

正如错误消息所说,问题出现在关闭期间。所以造成你麻烦的不是presentModalViewController,而是dismissViewControllerAnimated

如果您可以为该调用粘贴一些上下文,我们可能会找到解决方案。

【讨论】:

【参考方案3】:

试着改成这样:

[self.navigationController presentModalViewController:cust animated:NO];

【讨论】:

【参考方案4】:

也许尝试从导航控制器而不是 customAlertLoad 中解散:

[self.navigationController dismissViewControllerAnimated:NO completion:^

    CustomAlertMsg *cust = [[CustomAlertMsg alloc] init];
    cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    cust.modalPresentationStyle = UIModalPresentationFormSheet;
    cust.delegate = self;

    [self.navigationController presentModalViewController:cust animated:YES];
    cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
    cust.view.superview.center = self.view.center;

];

【讨论】:

【参考方案5】:

试试这个,

[customAlertLoad dismissViewControllerAnimated:NO completion:^ 

     [self performSelector:@selector(pushView) withObject:ni afterDelay:0.4];



-(void)pushView
     CustomAlertMsg *cust = [[CustomAlertMsg alloc] init];
     cust.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
     cust.modalPresentationStyle = UIModalPresentationFormSheet;
     cust.delegate = self;

     [self.navigationController presentModalViewController:cust animated:YES];
     cust.view.superview.frame = CGRectMake(0, 0, 458, 230);
     cust.view.superview.center = self.view.center;

【讨论】:

以上是关于显示为模态的两个导航控制器上的警告的主要内容,如果未能解决你的问题,请参考以下文章

如何更改模态视图 iOS 6 上的状态栏

模态显示的表格视图没有导航栏

Swift:强制在模态中显示导航栏

模态视图导航栏未正确显示

在带有分段控件的 UITabBarController 中模态显示导航视图控制器

如何将两个视图控制器显示为模态但仅对第二个进行动画转换?