我在iPad应用程序中有一个带有6个项目的标签栏控制器。当您点击它们时,其中两个图标将指向相同的视图控制器。此视图控制器具有将显示的项目列表,它将根据您点击的哪个标签栏图标稍微改变。
我如何用故事板设置它?可以将关系拖动两次到同一个视图控制器,但它只是在标签栏上显示两个相同的图标。我希望这两个选择有不同的图标和名称。
我遇到了类似的问题并且很容易解决。
在Storyboard中创建一个TabBarController。
在每个选项卡中分配导航控制器。
将所有导航控制器设置为Root View Controller,即要在它们之间共享的一个视图控制器。
在View Controller中,在ViewDidLoad中,根据tabBarController.selectedIndex创建条件,以根据所选选项卡自定义视图控制器。像这样的东西:
override func viewDidLoad() {
super.viewDidLoad()
if let selectedTabIndex = tabBarController?.selectedIndex {
switch selectedTabIndex:
case 0: // Customize ViewController for tab 1
case 1: // Customize ViewController for tab 2
case 2: // Customize ViewController for tab 3
default: break
}
我不认为你可以做你正在尝试用UITabBarController做的事情。如果需要,可以添加同一视图控制器类的两个不同实例。否则,您必须向常规UIViewController添加标签栏,并编写自己的逻辑以在控制器之间切换。
我能够通过在viewDidLoad中设置标签标题来实现这一目标。我为同一个View Controller创建了2个关系。然后我将条形项标题设置为“未设置”。最后,我将viewDidLoad方法设置如下:
UITabBarController *tc = (UITabBarController *)self.parentViewController;
NSArray *vcs = tc.viewControllers;
BOOL tabsInitialized=YES;
for (UIViewController *vc in vcs)
{
if ([vc.tabBarItem.title isEqualToString:@"Not Set"])
{
tabsInitialized = NO;
break;
}
}
if (!tabsInitialized)
{
int I=1;
for (UIViewController *vc in vcs)
{
vc.tabBarItem.title = [NSString stringWithFormat:@"Tab %i", i++];
}
}
}
我意识到这个问题已经回答了一段时间,但没有一个解决方案提到直接使用UITabBar
并覆盖其UITabBarDelegate
tabBar(:,didSelect item:)
方法,而不是让UITabBarController
间接处理选择。
extension MyListViewController: UITabBarDelegate {
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
// Set some filter based on the selected item or its tag (tag values can be assigned in IB)
switch item.tag {
// Apply filter to your datasource based on the item.tag
}
// Or if you are using a CoreData NSFetchedResultsController, set its predicate:
// resultsController.predicate = makePredicate(item.tag)
// resultsController.performFetch()
tableView.reloadData()
}
}
通过直接覆盖UITabBarDelegate
方法,您可以直接控制选项卡的选择行为。所以你可以重复使用你的UIViewController
的相同实例,而不是UITabBarController
为每个标签创建一个新的UIViewController
实例。例如,在didSelect
方法中,您可以将过滤器应用于UITableView
中的现有项目列表,而不是像其他解决方案那样在新的UITableView
中创建列表的新实例。
注意:如果你在代码或IB中的视图控制器中使用UITabBar
,UIKit似乎不会识别它的存在,并且“underlapping”滚动视图(例如UITableView
,UICollectionView
)将不会自动调整它们的contentInset
。如果你将它固定在安全区域的底部(它将看起来“浮动”,它自身和屏幕之间有一个间隙,它也不会固定在UITabBar
的底部正确地放置在具有非零安全区域边距的设备上-边缘)。
解决方案(第1部分):特别在UITabBar
实例上设置顶部约束:首先将标签栏的下边缘锚定到Superview
并将顶边固定到安全区域的底边并将常数设置为49(在撰写本文时,UITabBar的标准高度)。然后在具有和没有安全区域边距的设备上看起来是正确的。
解决方案(第2部分):您需要手动调整tableView.contentInset
/ collectionView.contentInset
以确保内容可以在标签栏下滚动。您需要确保最底部的项目仍然可以向上滚动到底部标签栏上方:
viewDidLoad()
中的自动内容插入调整:
tableView.contentInsetAdjustmentBehavior = .never
UIScrollView.contentInset
,添加以下方法并在viewDidLoad()
中调用它,或者每当视图在viewDidLayoutSubviews()
中放置时调用它。 (如果viewDidLoad()
对你来说太早了,viewWillAppear()
也可能太早了。)
private func adjustScrollViewInsets() {
// This snippet only insets the bottom of the table view, but you may need to adjust both top and bottom edges if you also need to accommodate a top navigation bar.
var contentInset = tableView.contentInset
if let windowInsets = view.window ?? UIApplication.shared.keyWindow?.safeAreaInsets {
contentInset.bottom = windowInsets.bottom
} else {
contentInset.bottom = 0
}
tableView.contentInset = contentInset
}