UISplitViewController: How force to show master popover in app launch? (portrait)

可紊 提交于 2019-12-03 04:27:22
Rob Elkin

I struggled with this one for a while, and even now I'm not 100% happy with the solution, but it is the only thing I've been able to come up with, given the current constraints.

First, override the following delegate method:

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

and use it to grab a reference to the bar button item, and store it in an iVar:

barButtonForMaster = barButtonItem;

Then, when you want to show the master view controller, make a call like this:

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

In case you want to perform this right at the start, then use some delay in order to prevent app crashing (thanks to the helpful comment):

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

In that case you can perform the selector right in the split view delegate method.

Martin

No suggestion here for 5.1, but one for 8.0:

Now with iOS8, there are a bunch of new methods for UISplitViewController configuration.

In your case, juste set the right value in preferredDisplayMode, for example in the masterViewController viewDidLoad.

Objective-C:

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

    //....
}

Swift:

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

But it's of course iOS8 only.

Extending on Rob's answer, this works well for me (in viewDidLoad of detail screen):

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

No need to fetch a separate reference, using self.navigationItem.leftBarButtonItem instead

For iOS8 the easiest way is with the following:

 self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;

I use this when the app is launched the first time for showing log-in in masterViewController. In all other cases I use

self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic

If you need it at app launch, override this method in your detail view controller:

-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
    return NO;
}

However if you then need it to subsequently hide it looks as though the method isn't called, so you'll have to manually hide it.

A slightly less hacky variation (swift):

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

I use this solution:
In splitViewController in viewDidLoad set displayMode to .primaryOverlay

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

And in viewWillAppear set it back to .automatic

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

This way master view will be shown at launch of UISplitViewController and have default behaviour after orientation will change.

user1021430

No need to keep silly references around to the barButtonItem. Simply call the same target/action. See my answer https://stackoverflow.com/a/25695923/1021430

The target is the split view controller, and the action is toggleMasterVisible:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!