iPad 模态控制器在旋转后被解散
Posted
技术标签:
【中文标题】iPad 模态控制器在旋转后被解散【英文标题】:iPad modal controller is dismissed after rotation 【发布时间】:2014-01-05 16:15:56 【问题描述】:我正在使用设置为Form Sheet
的故事板segue 呈现模态视图。
问题是,当我在显示此视图后旋转 iPad 时,该视图会从视图中删除/关闭。
我不知道为什么。它似乎只在以纵向开始然后旋转到横向时发生。
如果我从横向开始,然后显示视图然后旋转它就可以很好地停留在屏幕上。
有什么想法吗?
编辑----
似乎全屏模式视图在旋转后也被关闭了!
演示代码中没有什么特别之处,这是一个全屏模式:
EditViewController *editView = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:@"editViewController"];
editView.delegate = self;
editView.image = image;
editView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:editView animated:YES completion:nil];
这发生在 ios 6 和 iOS 7 上
编辑 2 ----
忘了提一下,我正在从 UISplitViewController
的左/主视图控制器展示模式
【问题讨论】:
你能显示展示模型的代码吗?这是哪个 ios 版本的? 没什么特别的,见编辑 我认为您从未放置过导致此问题的代码,请发布完整代码或检查是否有任何其他视图控制器会调用dismisspresentviewcontroller 方法。 嘿,你看过这个帖子吗?这个人也有类似的问题。 ***.com/a/13126655/437146 谢谢,是的,同样的问题。答案不是真正的解决方案,我不想让大师一直在屏幕上。 【参考方案1】:晚了,但它对我有用的是之前
[self presentViewController:aController animated:YES completion:nil];
关闭主控制器,添加此行
[self.splitViewController setPreferredDisplayMode:UISplitViewControllerDisplayModePrimaryHidden];
[self.splitViewController setPreferredDisplayMode:UISplitViewControllerDisplayModeAutomatic];
然后展示你的控制器
【讨论】:
很棒很棒很棒!我卡了一段时间,谢谢 对我来说难以解决的问题的简单解决方案。谢谢!【参考方案2】:摆脱:editView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; 这将解决您遇到的问题。在 iPad 上显示为表单表单的模态视图控制器无法使用该转换样式正确旋转。
【讨论】:
恐怕这行不通。问题仍然存在。加上这条线,我确实看到了 FlipHorizontal 过渡。 对不起,我应该提到,上面粘贴的代码是用于全屏模式,而不是表单模式。两个都出现问题 请原谅不正确的答案。几年前曾经是这样,但我只是重新验证,不再是这样了。在当前的 iOS 中,如果从主视图控制器呈现,无论使用哪种过渡样式,模式都会从纵向变为横向。看起来 splitViewController 可能在某处内部调用了dismissViewController。我认为我们应该提交错误报告。【参考方案3】:真的很难找到原因是如何以及为什么会发生这种情况,因为我发现 UIPopover 也会发生这种情况,当你旋转它时 UIPopover 隐藏因为 ???
因此,如果您想保留视图,那么只需在旋转后再次调用您的控制器即可获得良好的用户体验
【讨论】:
我实际上认为问题出在主视图和模态的所有权上。因为主视图实际上是一个弹出框,并且会在旋转时显示和删除。 和 UISplitViewController 已经像 popover 并且如果你从纵向旋转到横向它也会被关闭【参考方案4】:这不是一个错误,它是对UISplitViewController
的限制。当 masterViewController(UIPopoverController
)能够被解除时,问题就存在了。以下是假设您的应用确实允许 masterViewController 以纵向方式关闭而不允许以横向方式关闭的假设下它是如何工作的。
在 masterViewController 可见时纵向显示,如果您从 masterViewController 中的 viewController 呈现模态,然后旋转到横向,则模态将在 iOS7 中消失,而应用程序在 iOS8 中不会旋转。 iOS8引入了一个条件来防止iOS7的不良体验。 iOS7在将masterViewController从popoverController移动到splitViewController中包含的viewController的过程中丢失了modal。
模态框需要从 splitViewController 而不是 masterViewController 呈现。唯一的问题是模式在纵向的 masterViewController 下方呈现。我的解决方案是关闭 masterViewController,然后呈现模式。
根据您的代码需要的复杂程度,有多种方法可以实现此结果。以下是我在我的应用中执行此操作的方法。
我首先将UISplitViewController
子类化,以便引用popoverController。我使用委托转发以便在内部和外部访问委托方法。这是.h
// MainSplitViewController.h
#import <UIKit/UIKit.h>
@interface MainSplitViewController : UISplitViewController
@property (nonatomic, weak, readonly) UIPopoverController* primaryColumnController;
@end
还有.m
// MainSplitViewController.m
#import "MainSplitViewController.h"
@interface MainSplitViewController () <UISplitViewControllerDelegate>
@property (nonatomic, weak) id<UISplitViewControllerDelegate> externalDelegate;
@property (nonatomic, weak) UIPopoverController* primaryColumnController;
@end
@implementation MainSplitViewController
- (instancetype)init
self = [super init];
if (self)
self.delegate = self;
return self;
#pragma mark - Split View Controller Delegate
- (void)splitViewController:(UISplitViewController *)svc popoverController:(UIPopoverController *)pc willPresentViewController:(UIViewController *)aViewController
self.primaryColumnController = pc;
if ([(id)self.externalDelegate respondsToSelector:_cmd])
[self.externalDelegate splitViewController:svc popoverController:pc willPresentViewController:aViewController];
#pragma mark - Delegate Forwarder
- (void)setDelegate:(id<UISplitViewControllerDelegate>)delegate
[super setDelegate:nil];
self.externalDelegate = (delegate != self) ? delegate : nil;
[super setDelegate:delegate ? self : nil];
- (BOOL)respondsToSelector:(SEL)aSelector
id delegate = self.externalDelegate;
return [super respondsToSelector:aSelector] || [delegate respondsToSelector:aSelector];
- (id)forwardingTargetForSelector:(SEL)aSelector
id delegate = self.externalDelegate;
return [delegate respondsToSelector:aSelector] ? delegate : [super forwardingTargetForSelector:aSelector];
@end
接下来我在UIViewController
上创建一个类扩展
// UIViewController+Popover.h
#import <UIKit/UIKit.h>
@interface UIViewController (Popover)
- (UIViewController *)popoverPresentingViewController;
@end
还有.m
// UIViewController+Popover.m
#import "UIViewController+Popover.h"
#import "MainSplitViewController.h"
@implementation UIViewController (Popover)
- (UIViewController *)popoverPresentingViewController
UIViewController* viewController = self;
if ([self.splitViewController isKindOfClass:[MainSplitViewController class]])
viewController = self.splitViewController;
MainSplitViewController* mainSplitViewController = (MainSplitViewController *)self.splitViewController;
if (mainSplitViewController.primaryColumnController.popoverVisible)
[mainSplitViewController.primaryColumnController dismissPopoverAnimated:YES];
return viewController;
@end
现在无论你在哪里展示模态,而不是调用[self presentViewController: ...
调用[self.popoverPresentingViewController presentViewController: ...]
。记得导入 UIViewController+Popover.h
【讨论】:
【参考方案5】:您的问题最接近我的错误,从 modalView 返回时,parentView 将切换到打开应用程序的方向。 从视觉上看,模态视图似乎被旋转然后返回。
我通过完全删除模态视图并使用
解决了这个问题[self.navigationController pushViewController: <the View(not modal now)>]
而不是使用-
[self presentViewController:<Modal View>]
我认为这是因为导航控制器不拥有模态视图,因此它重新加载 - 当从模态视图返回时 - 方向不正确
【讨论】:
【参考方案6】:问题:
当以模态方式呈现视图控制器时,它会在旋转时被关闭。
方法:
设置UISplitViewControllerDelegate
使用UISplitViewControllerDelegate
方法
在实例变量中保存对模态视图控制器的引用
检查模态视图控制器的呈现视图控制器是否存在。
如果存在,则无需执行任何操作,否则直接呈现而无需任何动画。
UISplitViewControllerDelegate
方法:
func primaryViewController(forCollapsing splitViewController: UISplitViewController) -> UIViewController?
if let someModalViewController = someModalViewController,
someModalViewController.presentingViewController == nil
let masterViewController = viewControllers.first
masterViewController?.present(someModalViewController,
animated: false)
return nil
func primaryViewController(forExpanding splitViewController: UISplitViewController) -> UIViewController?
if let someModalViewController = someModalViewController,
someModalViewController.presentingViewController == nil
let masterViewController = viewControllers.first
masterViewController?.present(someModalViewController,
animated: false)
return nil
注意:
UISplitViewControllerDelegate
有很多方法,一开始可能会让人望而生畏,如果你花一些时间去尝试,你可以达到你想要的。
它具有细粒度的访问权限。
【讨论】:
【参考方案7】:我很晚了,但试试这个。它对我有用。
[self.splitViewController presentViewController:editView animated:YES completion:nil];
【讨论】:
以上是关于iPad 模态控制器在旋转后被解散的主要内容,如果未能解决你的问题,请参考以下文章
将模态视图控制器解散回嵌入在 TabBarController 中的导航控制器堆栈导致崩溃
UIViewController 在解除先前呈现的模态视图控制器后被释放