UISplitViewController:如何强制在应用启动时显示主弹出框? (肖像)

Posted

技术标签:

【中文标题】UISplitViewController:如何强制在应用启动时显示主弹出框? (肖像)【英文标题】:UISplitViewController: How force to show master popover in app launch? (portrait) 【发布时间】:2012-05-03 07:02:51 【问题描述】:

在 iPad 应用程序中,我使用的是 UISplitViewController。 当应用以纵向模式启动时,我需要强制显示主弹出框。

现在我正在使用此代码,它在 ios 5.0 上运行良好。

if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) 
   if ([[[AppDelegate sharedAppDelegate] splitViewController] respondsToSelector:[[[AppDelegate sharedAppDelegate] btnMenu] action]]) 
      [[[AppDelegate sharedAppDelegate] splitViewController] performSelector:[[[AppDelegate sharedAppDelegate] btnMenu] action]];
               

但在 iOS 5.1(使用新型主弹出框)中,行为似乎是随机的。 有时弹出框会全屏显示,有时效果很好。

对 5.1 的一些建议?

【问题讨论】:

这是一个很好的答案:***.com/a/15817100/733862 【参考方案1】:

这里没有 5.1 的建议,但 8.0 的建议:

现在在 iOS8 中,UISplitViewController 配置有很多新方法。

在您的情况下,只需在 preferredDisplayMode 中设置正确的值,例如在 masterViewController viewDidLoad 中。

目标-C:

- (void)viewDidLoad 
    // configuring splitviewcontroller
    self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;

    //....

斯威夫特:

    override func viewDidLoad() 
        self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
    

但当然仅限 iOS8。

【讨论】:

这会强制并排显示。它不会按照 OP 的要求在弹出模式下显示主视图。 @phatmann,我认为 alejandromp 不是在谈论 popover。他说我需要强制显示主弹出框,但实际上这并不意味着什么。考虑到上下文,他确实谈到了在纵向模式下并排显示主视图,就像在横向模式中一样。 也可以调用detailViewController【参考方案2】:

我在这个问题上苦苦挣扎了一段时间,即使现在我对这个解决方案也不是 100% 满意,但考虑到当前的限制,这是我唯一能想到的。

首先,重写以下委托方法:

- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController

并使用它来获取对条形按钮项的引用,并将其存储在 iVar 中:

barButtonForMaster = barButtonItem;

然后,当您想要显示主视图控制器时,请进行如下调用:

[barButtonForMaster.target performSelector: barButtonForMaster.action withObject: barButtonForMaster];

如果您想在开始时正确执行此操作,请使用一些延迟以防止应用崩溃(感谢有用的评论):

[barButtonForMaster.target performSelector: barButtonForMaster.action withObject: barButtonForMaster afterDelay:1];

在这种情况下,您可以在拆分视图委托方法中直接执行选择器。

【讨论】:

谢谢。我用你的代码加上我以前的代码来做这个。但有时应用程序崩溃。我认为这是因为我在 splitViewController 委托中执行此操作,并且在某些情况下,它可能是未完全创建的控制器。现在我用 perfromSelectorAfterDelay 编写代码并且工作得很好。谢谢。 这将导致编译器可能出现内存泄漏警告【参考方案3】:

扩展 Rob 的回答,这对我很有效(在详细屏幕的 viewDidLoad 中):

//If in portrait mode, display the master view
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) 
    [self.navigationItem.leftBarButtonItem.target performSelector:self.navigationItem.leftBarButtonItem.action withObject:self.navigationItem];

无需获取单独的引用,而是使用 self.navigationItem.leftBarButtonItem

【讨论】:

这太棒了,而且效果很好!但是它给了我一个警告,“PerformSelector 可能会导致泄漏,因为它的选择器是未知的”你知道为什么以及如何处理它吗? AFAIK 编译器分析方法调用并添加代码来管理 ARC 引用计数器(以管理垃圾收集)。调用这样的方法有点像在 Java 中使用反射(在运行时完成),因此在这种情况下编译器无法发挥其 refCount 魔法。但是,只要调用的方法不返回任何分配的对象(这将是一个泄漏),它就不会有任何问题。在这种情况下,我们不会从被调用的方法返回任何内容。为避免此警告,请参阅:learningipadprogramming.com/2012/04/03/… 如果细节视图控制器中没有加载任何内容,这将不起作用,这将是强制主显示的要点。 @VictorEngel 确实如此,但由于此代码进入详细视图,因此您需要确保默认加载一个空的详细视图。【参考方案4】:

对于 iOS8,最简单的方法是:

 self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;

我在第一次启动应用程序时使用它来显示 masterViewController 中的登录。 在所有其他情况下,我使用

self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic

【讨论】:

【参考方案5】:

如果您在应用启动时需要它,请在您的详细视图控制器中覆盖此方法:

-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation

    return NO;

但是,如果您随后需要它隐藏它,它看起来好像没有调用该方法,所以您必须手动隐藏它。

【讨论】:

这在 iOS 8 中已被弃用。【参考方案6】:

稍微不那么老套的变体(swift):

let btn = self.splitViewController!.displayModeButtonItem()
btn.target?.performSelector(btn.action, withObject: btn)

【讨论】:

【参考方案7】:

我使用这个解决方案: 在 viewDidLoad 的 splitViewController 中将 displayMode 设置为 .primaryOverlay

override func viewDidLoad() 
    if self.isCollapsed == false, self.displayMode == .primaryHidden 
        self.preferredDisplayMode = .primaryOverlay
    

在 viewWillAppear 中将其设置回 .automatic

override func viewWillAppear(_ animated: Bool) 
    self.preferredDisplayMode = .automatic

这样主视图将在 UISplitViewController 启动时显示,并且在方向改变后具有默认行为。

【讨论】:

【参考方案8】:

无需保留对 barButtonItem 的愚蠢引用。只需调用相同的目标/动作。看我的回答https://***.com/a/25695923/1021430

target是split view controller,action是toggleMasterVisible:

【讨论】:

toggleMasterVisible 是一个私有方法。

以上是关于UISplitViewController:如何强制在应用启动时显示主弹出框? (肖像)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 uisplitviewcontroller 在纵向模式下并排设置主视图/详细视图

如何在横向全屏 UISplitViewController 的 DetailView

关闭uisplitviewcontroller中的NavigationController后如何重新加载tableView?

如何在 UISplitViewController 的导航栏下方添加搜索栏?

UISplitViewController:如何强制在应用启动时显示主弹出框? (肖像)

UISplitViewController - 主弹出框 - 肖像模式:如何自定义/删除最顶层的边框?