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

问题描述 投票:9回答:2

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

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

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

ios delegates uitabbarcontroller
2个回答
8
投票

我在this question找到了我需要的东西。

基本上,您为“更多”选项卡中显示的导航控制器设置了UITabBarControllerDelegateUINavigationControllerDelegate。之后,您将检测用户是否触摸了其中一个可见选项卡或“更多”选项卡。

编辑

此外,要直接操作“更多”导航控制器中可见的表,您可以设置“中间人”表视图委托,该委托拦截对原始委托的调用。请参阅以下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];
}

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中实现一些其他委托方法,则该委托拦截可能存在潜在问题。

© www.soinside.com 2019 - 2024. All rights reserved.