到目前为止,我已经解决了这个问题:在 viewWillAppear 中,所有细节控制器都是从标签栏的导航控制器中删除的。存储状态时,会保存设备方向和 SplitViewController.viewControllers(对我来说,它不会像在 iOS7 上那样自动存储它们)。
- (void) encodeRestorableStateWithCoder:(NSCoder*)coder
{
[super encodeRestorableStateWithCoder:coder];
[coder encodeObject:self.viewControllers forKey:@"viewControllers"];
[coder encodeInteger:[UIApplication sharedApplication].statusBarOrientation forKey:@"orientation"];
}
- (void) decodeRestorableStateWithCoder:(NSCoder*)coder
{
[super decodeRestorableStateWithCoder:coder];
NSArray* viewControllers = [coder decodeObjectForKey:@"viewControllers"];
if (viewControllers.count > 0)
{
self.viewControllers = viewControllers;
}
restoredOrientation = (UIInterfaceOrientation) [coder decodeIntegerForKey:@"orientation"];
}
这是 viewWillAppear 的实现:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// iPhone6+: if state restoration happened while in portrait orientation and app is launched while in landscape,
// then all detail views should be cut from master view and split details view is set appropriately
if (firstLoad &&
[UIScreen mainScreen].scale > 2.9 && // assure it's iPhone 6+
UIInterfaceOrientationIsPortrait(restoredOrientation) &&
UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation))
{
UITabBarController* tbc = self.viewControllers[0];
NSArray* detachedControllers = [tbc cutControllersFrom:DocumentViewController.class];
if (detachedControllers.count > 0)
{
UINavigationController* documentNavigation = [self.storyboard
instantiateViewControllerWithIdentifier:@"NavigationController"];
documentNavigation.viewControllers = detachedControllers;
self.viewControllers = @[ self.viewControllers[0], documentNavigation ];
}
else // place some default no-selection controller in detail
{
UINavigationController* noSelectionNavigation = [self.storyboard
instantiateViewControllerWithIdentifier:@"NoSelectionSID"];
self.viewControllers = @[ self.viewControllers.firstObject, noSelectionNavigation ];
}
}
firstLoad = NO;
}
其中 cutControllersFrom 方法是 UITabBarController 上的一个类别:
- (NSArray*) cutControllersFrom:(Class)controllerClass
{
NSArray* ret;
for (UIViewController* vc in self.viewControllers)
{
if (![vc isKindOfClass:UINavigationController.class])
{
continue;
}
UINavigationController* nc = (UINavigationController*) vc;
NSArray* removed = [nc cutFrom:controllerClass];
if (vc == self.selectedViewController)
{
ret = removed;
}
}
return ret;
}
它调用 cutFrom: 方法,它是 UINavigationController 上的一个类别:
- (NSArray*) cutFrom:(Class)controllerClass
{
NSMutableArray* toRemove = [NSMutableArray array];
BOOL startRemoving = NO;
UIViewController* endingViewController;
for (NSUInteger i = 0; i < self.viewControllers.count; i++)
{
UIViewController* vc = self.viewControllers[i];
if ([vc isKindOfClass:controllerClass])
{
startRemoving = YES;
endingViewController = self.viewControllers[i - 1];
}
if (startRemoving)
{
[toRemove addObject:vc];
}
}
if (endingViewController)
{
[self popToViewController:endingViewController animated:NO];
}
return toRemove;
}