UISplitViewController Cannot Change the Master View Controller?

老子叫甜甜 提交于 2019-12-05 08:13:39
SMSidat

In case anyone is looking for a solution to this issue (or a word-around), I had a similar issue and worked it out here: Changing the master view in Split View does not update the popover in portrait

Basically, I used a navigation controller for the master view controller, and pushed/poped view controllers within that navigation controller, in order to change view controllers in the master view whilst still displaying the correct viewcontroller in portrait orientation, in the popup view.

UPDATED: please read final update at bottom! Oiginal answer + update below may not be useful!

We have just had exactly the same problem. Sometimes I wonder if Apple actually test the classes they write with anything resembling realistic use cases, because UISplitViewController is not their finest moment.

The problem is that when you replace the master view controller in the split view, the code inside UISplitViewController doesn't update its popover controller's contentViewController property. The result is that the popover controller still has a handle on an out of date view controller, resulting in old UIs appearing, or even memory faults, when in portrait mode.

Here is our workaround.

I will assume that you have a UISplitViewControllerDelegate conforming class which stores the popoverController as a class property (see the standard sample code for UISplitViewController).

At the point at which you set the new master view controller, you also need to update the contentViewController, as follows:

mySplitViewController.viewControllers
    = [NSArray arrayWithObjects:newMasterController, detailController, nil];

// in the cases where the uisplitview has already shown a popovercontroller,
// we force the popovercontroller to update its content view controller. 
// This ensures any old content view in popover actually gets released by 
// the popovercontroller.
if (popoverController) {
    [popoverController setContentViewController:theMasterViewController 
                                animated:NO];       
}

You also must set the popover's contentViewController when your UISplitViewControllerDelegate gets informed that the popover controller is going to present a view controller:

- (void)splitViewController:(UISplitViewController*)svc 
        popoverController:(UIPopoverController*)pc 
        willPresentViewController:(UIViewController *)aViewController 
{
    // set the popoverController property - as per Apple's sample code
    self.popoverController = pc;

    // THE LINE BELOW IS THE NEW LINE!
    [popoverController setContentViewController:aViewController animated:NO];

Yes, I know the above code looks insane, and you're wondering why apple couldn't just set the content view controller themselves. But they apparently don't, and this is the fix.

UPDATE

The above scheme, with setting the content view, turns out not to work after all. For example, if you set the content view to be a uinavigationcontroller, later on you get passed the root view inside the nav controller, instead of the nav controller itself. UISplitViewController just doesn't handle changing the master view in any workable way, as far as I can see.

The workaround I currently have is to install a UINavigationController as the master view, and change the root view controller of that nav controller. So I get to change the master view 'by the back door', in a way.

UPDATE 2

I give up. The approach in the first update above is flawed too; I get problems upon rotation still. Basically, it seems that if you use UISplitViewController, you shouldn't attempt any changing of the master view controller (even if you're switching the master view when the master view, e.g. as a popover, has been hidden again). Fiddling with the contents of a UINavigationController in the master view (while the master view is showing) appears like it will be ok, but anything beyond that leads to problem after problem.

Technical note: I believe the problems stem from an apparent weakness in Apple's handling of UIs: namely, Apple code will call release on UIViews and controller once hidden or removed from view, but will then later, if the containing viewcontroller is shown again, send deferred messages like viewDidDisappear to the released views/controllers (which at that point may have been deallocated).

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