当在“更多”部分时,didSelectViewController没有被调用

10

我有一个UITabBarController并且已经设置了它的代理方法didSelectViewController,因为我想知道用户选择的标签的索引。

然而,我注意到当用户在“更多”部分(当有更多的标签无法显示在tabbar中时)时,didSelectViewController方法不会被调用:

The problematic section

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


我也尝试过解决这个问题。我可以知道他们何时点击了“更多”,但要查看他们从“更多”视图控制器的表视图中选择了哪个视图控制器,需要使用非公开的API调用。 - Greg Combs
2个回答

9

我在这个问题中找到了所需的内容。

基本上,您需要为在“更多”选项卡中显示的导航控制器设置一个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];
}

你尝试过同时使用 NSLog 和 delegate 来查看它们是否不同吗?看起来它们是一样的。 - Tung Do

1

之前的答案几乎正确,但缺少一个方法以使其正常工作。

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。如果我们查看其实现,我们会注意到这两个重写的函数:didSelectwillDisplay

注意:

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


嗯,我已经完全忘记这是关于什么的了,因为那已经是将近7年前的事情了... - Shade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接