UISplitViewController not showing popup button whe

2019-04-03 17:54发布

问题:

I am doing an iPad app based on a UISplitViewController. I have a little problem with the toobar button when my app launched in potrait. The button to show the popover is not displayed. However when I rotate my iPad into landscape and then back to portrait, the button shows !

It looks like the following method is not called on launch (this is were I have the code showing the button):

- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController: (UIPopoverController *)pc

This method is not called when the app launches but only when there is a rotation. What is even stranger is that I made a test app using Xcode UISplitViewController template + core data (which is similar to the app I am working on, and is the template I used to make this app). On the test app on which I have not made a single line of code, the button shows when I launch my app in portrait mode and the method above is also called upon launching, as opposed to my other app. Does anyone had a similar problem ?

Finally, it is not very clear from apple documentation whether this method is supposed to be called when a UISplitViewController is first shown: http://developer.apple.com/library/ios/#documentation/uikit/reference/UISplitViewControllerDelegate_protocol/Reference/Reference.html%23//apple_ref/doc/uid/TP40009454

回答1:

"Kshitiz" has the right concept. first I set the self.splitviewController.delegate = self in the viewDidLoad method, which it is a bit late to set this delegation. So, I tried to set the delegation in earlier stage which is awakeFromNib method. Then it works well.

So, the problem is after view already loaded by viewDidLoad, then the delegation will not work, it will work some time after some activities (such as rotate the iPad). So the earlier stage than viewDidLoad is awakeFromNib.

Here is the code that works:

- (void) awakeFromNib{
    [super awakeFromNib];
    self.splitViewController.delegate = self;
}


回答2:

Have you set a splitviewcontroller delegate? Generally the problem arises when delegate is not set.



回答3:

I was having the exact same problem, and Martin Gunnarsson's response led me to the solution.

Before, I was setting the UISplitViewController's delegate property after the delegate view (the detail view) had already been loaded, in viewDidLoad:. By this time, the UISplitViewController had already sent the initial splitViewController:willHideViewController:withBarButtonItem:forPopoverController: message. I simply hadn't set the delegate soon enough.

The solution was to assign the delegate in the main app delegate, in application:DidFinishLaunchingWithOptions:. In this case, my delegate was contained within a navigation controller, so I had to dig one layer deeper to get it.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
    UINavigationController *mainNavigationController = (UINavigationController *)[splitViewController.viewControllers objectAtIndex:1];
    HPMainViewController *mainViewController = [mainNavigationController.viewControllers objectAtIndex:0]; 

    splitViewController.delegate = mainViewController;
    return YES;
}


回答4:

This drove me spare as well, the more so since I'm working on two iPad projects with out-of-the-box splitViewController and the first one always shows the 'Master' button while the second one never did. I compared outlets and relationships and delegates until I was cross-eyed, but finally found the answer in the appDelegate. It turned out I had commented out a bit too much in the application:didFinishLaunchingWithOptions:, specifically where the splitViewController.delegate is set.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
        UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
        splitViewController.delegate = (id)navigationController.topViewController;
    }

Adding this to the appDelegate saves you from having to subclass the splitViewController. I also tried connecting the delegate in IB, but for some reason it wouldn't have none of that. Storyboard design flaw, imho.



回答5:

I was stuck on this for quite sometime. Finally got it to work. The awakeFromNib did not work for me. The didFinishLaunchingWithOptions did. Might be because I am running some query that populates the items in the popover controller.



回答6:

I'm having the same issue. My view is set up in IB, and it seems this is a timing issue. The split view delegate gets set after the split view has notified about the initial orientation "change". Adding the split view to an outlet in the app delegate made the button appear at portrait startup for me, but when I open the popup it's empty. This can probably be worked around somehow, but I think it's weird that the split view doesn't notify its delegate about the current orientation when it's set.