在“更多”部分中没有调用didSelectViewController

时间:2011-04-27 11:31:29

标签: ios delegates uitabbarcontroller

我有一个UITabBarController并且我已经设置了它的委托方法didSelectViewController,因为我对正在选择的选项卡的索引感兴趣。

但是,我注意到当用户处于“更多”部分时(当标签栏中显示的标签多于标签栏时),didSelectViewController方法不会被调用:

The problematic section

有没有办法让我收到用户从自动创建的表格中选择的项目的通知?

2 个答案:

答案 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,我们会注意到这两个覆盖的函数:didSelectwillDisplay

注意:

如果Apple决定在未来的iOS版本中以自己的UIMoreListController实现其他委托方法,则委托拦截可能存在潜在的问题。