我有一个UITabBarController并且我已经设置了它的委托方法didSelectViewController
,因为我对正在选择的选项卡的索引感兴趣。
但是,我注意到当用户处于“更多”部分时(当标签栏中显示的标签多于标签栏时),didSelectViewController
方法不会被调用:
有没有办法让我收到用户从自动创建的表格中选择的项目的通知?
答案 0 :(得分:8)
我在this question找到了我需要的东西。
基本上,您为“更多”标签内显示的导航控制器设置了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];
}
答案 1 :(得分:0)
先前的答案几乎是正确的,因为它错过了一种可以正常工作的方法。
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
。如果我们看一下其implementation,我们会注意到这两个覆盖的函数:didSelect
和willDisplay
。
注意:
如果Apple决定在未来的iOS版本中以自己的UIMoreListController
实现其他委托方法,则委托拦截可能存在潜在的问题。