我有一个UITabBarController并且已经设置了它的代理方法didSelectViewController
,因为我想知道用户选择的标签的索引。
然而,我注意到当用户在“更多”部分(当有更多的标签无法显示在tabbar中时)时,didSelectViewController
方法不会被调用:
有没有办法让我得到关于用户从自动创建的表格中选择的项目的通知?
我有一个UITabBarController并且已经设置了它的代理方法didSelectViewController
,因为我想知道用户选择的标签的索引。
然而,我注意到当用户在“更多”部分(当有更多的标签无法显示在tabbar中时)时,didSelectViewController
方法不会被调用:
有没有办法让我得到关于用户从自动创建的表格中选择的项目的通知?
我在这个问题中找到了所需的内容。
基本上,您需要为在“更多”选项卡中显示的导航控制器设置一个UITabBarControllerDelegate
和一个UINavigationControllerDelegate
。之后,您可以检测用户是否触摸了其中一个可见选项卡或“更多”选项卡。
编辑
此外,要直接操作“更多”导航控制器中可见的表格,您可以设置一个“中间人”表格视图代理,拦截对原始代理的调用。请参见下面didSelectViewController
中的代码:
if (viewController == tabBarController.moreNavigationController && tabBarController.moreNavigationController.delegate == nil) {
// here we replace the "More" tab table delegate with our own implementation
// this allows us to replace viewControllers seamlessly
UITableView *view = (UITableView *)self.tabBarController.moreNavigationController.topViewController.view;
self.originalDelegate = view.delegate;
view.delegate = self;
}
之后,您可以在委托方法内自由进行任何操作,只要在另一个委托中调用相同的方法即可(我实际上检查了原始委托响应的方法,唯一实现的委托方法是didSelectRow:forIndexPath:
)。以下是示例:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// this is the delegate for the "More" tab table
// it intercepts any touches and replaces the selected view controller if needed
// then, it calls the original delegate to preserve the behavior of the "More" tab
// do whatever here
// and call the original delegate afterwards
[self.originalDelegate tableView: tableView didSelectRowAtIndexPath: indexPath];
}
之前的答案几乎正确,但缺少一个方法以使其正常工作。
class MyClass: ... {
var originalTableDelegate: UITableViewDelegate?
}
extension MyClass: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if viewController == tabBarController.moreNavigationController && originalTableDelegate == nil {
if let moreTableView = tabBarController.moreNavigationController.topViewController?.view as? UITableView {
originalTableDelegate = moreTableView.delegate
moreTableView.delegate = self
}
}
}
}
extension MyClass: UITableViewDelegate {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
originalTableDelegate!.tableView!(tableView, willDisplay: cell, forRowAt: indexPath)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("intercepted")
originalTableDelegate?.tableView!(tableView, didSelectRowAt: indexPath)
}
}
原始表格代理在更多控制器上实际上是系统隐藏类UIMoreListController
。如果我们查看其实现,我们会注意到这两个重写的函数:didSelect
和willDisplay
。
注意:
如果苹果在未来的iOS版本中决定在其自己的UIMoreListController
中实现其他委托方法,则可能存在此委托拦截的潜在问题。