电路:iPhone 6 Plus,UISplitViewController
在水平方向上旋转紧凑(折叠)和水平方向上常规(展开)大小的类。
问题:在折叠的UISplitViewController
中,似乎无法检测主(最左边,主)视图控制器之上的细节(最右边,辅助)视图控制器何时被解除。在详细信息视图控制器中,对于isMovingFromParentViewController
和isBeingDismissed
,viewWillDisappear:
和viewDidDisappear:
始终报告NO。UISplitViewController
viewControllers
数组属性不具有指示性。
原因:此问题是相关的,因为如果局部视图控制器在解除时未标记为(逻辑上)"空"(即"已清除"),则在随后的UISplitViewController
展开时,局部视图控制器将重新显示潜在的(逻辑上的)无关内容。此外,当展开的UISplitViewController
折叠时,它无法选择是仅显示主视图控制器,还是通过受人喜爱的命名为splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
的委托方法在主视图控制器上显示局部视图控制器。
似乎您正试图让详细信息视图控制器处理将自己标记为"空"的
我建议将该逻辑移动到主视图控制器,这样它也可以处理除旋转之外的其他情况,例如当新结果到达时,或者用户搜索(过滤)结果时。
让主视图控制器处理局部视图的更新(通过将其细节标记为零,或者最好传递新的细节)。
您的拆分视图控制器代理将能够确定如何处理辅助视图控制器,并且您的局部视图控制器代码也将更易于维护,因为它不了解数据源,也不(紧密)耦合到数据源。
更新:
没有主UISplitViewController
displayMode
,其中无法显示辅助。显示模式都显示次要VC,但可以显示、隐藏或覆盖主要VC。用户可以旋转设备,或显示或隐藏主要VC(通过presentsWithGesture
或displayModeButtonItem
),但对于常规大小的类,次要VC将始终显示,无论是否为空。
以下是苹果的Master Detail模板代码如何确定当设备转换为水平紧凑尺寸类时,辅助VC是应该折叠还是丢弃。
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[YHWHDetailViewController class]] && ([(YHWHDetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
// Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return YES;
} else {
return NO;
}
}
请注意,Apple使用局部视图控制器上的属性作为标志。
我知道你认为,应该根据用户是否明确拒绝次要VC(以水平紧凑的大小折叠时)来决定是折叠还是丢弃次要VC。
我知道,当VC消失时,你试图让细节"清晰"起来,但假设它被驳回(丢弃),并且你没有强烈提及它,那将是不可行的。
如果细节不存在(或者dataSource
使细节无效),情况会更简单。
如果你一直在坚持,但无法清除细节,你要么必须:
- 保留某种类型的标志(无论是BOOL还是nil对象),以反映细节的内容是否已变得"不相关",并依靠该标志来确定将来是否应该(再次)折叠次视图控制器
- 对照
dataSource
检查细节(在再次折叠之前),查看其内容是否"相关"或"无关"
如果你使用一个细节VC属性作为标志,这里有好处。当SVC崩溃,详细VC被"明确驳回"时,就不再有次要VC从主要VC中分离出来。
- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController
separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController{
if ([primaryViewController isKindOfClass:[UINavigationController class]]) {
for (UIViewController *controller in [(UINavigationController *)primaryViewController viewControllers]) {
if ([controller isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)controller visibleViewController] isKindOfClass:[DetailViewController class]]) {
return controller;
}
}
}
// No detail view present
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UINavigationController *secondaryViewController = [storyboard instantiateViewControllerWithIdentifier:@"SecondaryViewController"];
// Ensure back button is enabled
UIViewController *detailViewController = [secondaryViewController visibleViewController];
detailViewController.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
detailViewController.navigationItem.leftItemsSupplementBackButton = YES;
return secondaryViewController;
}
因为您实例化了一个"空白"的详细VC,所以当用户将SVC从常规大小旋转回紧凑大小时,SVC代理可以看到没有要显示的详细信息,因此它将丢弃辅助VC。
这是苹果的方法,效果非常好,因为它通过旋转、手势或显示模式按钮将SVC是折叠还是扩展的控制权留给了用户。
我相信你已经在6 Plus上看到了苹果的邮件应用程序。不过,请注意,一旦用户回到常规尺寸的类别,苹果会做什么。即使用户弹回消息列表,当详细信息再次出现时,先前选择的消息仍会显示。
如果有可能让你的应用程序也这样做,我会鼓励它。它友好、方便、有回报,因为它节省了用户进行(重新)选择的时间,并显示详细信息而不是空白视图。
当iPhone从折叠显示转换为展开显示(即从纵向显示转换为横向显示)时,主机将收到对-viewWillAppear:
的调用。在那里,您可以决定显示一个空的局部视图控制器或一个填充的"有效"局部视图控制器,这取决于在主控形状中选择的内容(或者根本没有选择任何内容),这样您就可以丢弃任何以前显示的具有潜在无效数据的局部视图控件。
但我看不出细节视图控制器在从展开到折叠的过渡中应该如何显示不相关的内容。虽然主控器是不可见的,但它仍然完好无损,细节视图控制器也应该是。