我的UI结构如下:
UITabBarController( TBC )-> UINavigationController( NC )-> UITableViewController( TVC )

(为简化示例,可以说 TBC viewControllers数组上只有一个 Controller - NC )

我的 TVC UISearchBar作为其表标题,当 TVC 出现时,我通过设置表格 View 内容偏移量来将搜索栏隐藏在 NC 导航栏下方。

当用户点击 TVC 中的单元格时,将推另一个 View Controller ( VC ),并使用VC.hidesBottomBarWhenPushed = YES;隐藏选项卡栏

现在有一个非常烦人的行为,我不知道该如何解决:
当用户将后退按钮从 VC 返回到 TVC 时,即使在按下 VC 之前将其隐藏(在导航栏下方),搜索栏也会跳转为可见。

仅当 TVC 没有足够的行来填充屏幕时,才会发生这种效果,就像在屏幕上有一个位置时,搜索栏一样,它本身必须可见。但它看起来确实很糟糕而且有故障。

我上传了一个simple project来演示问题,它的结构与我在问题中描述的结构相同。
为了方便起见,我添加了两个栏按钮,“隐藏栏”按钮为您隐藏了搜索栏,而“切换计数”按钮切换了表格 View 的行数,以证明仅当项目很少时才会出现此问题。

最佳答案

好吧..在我看来,您偶然发现了一个错误。应该通过apples bugreporter(here)报告。

我已经做了一个简单的解决方法,但请记住解决方法。这将起作用,但是如果您向tableView中添加了其他控件,则可能必须对其进行检查。它应该安全使用(不能随机执行),并且不是最丑陋的解决方法,因此我认为在发行版中使用是可以的。我已经上传了具有修复程序here 的同一个项目,您可以继续下载该文件,您可能会了解我的所作所为。如果将来下载链接消失了,我将在这里(非常详细地)解释我实际上的想法和所做的事情:

思路:

就像simalone所说的那样,问题在于,当hidesBottomBarWhenPushed设置为YES时,它将调用附加的viewDidLayoutSubviews,从而以某种方式重置您的当前状态。我们需要重写viewDidLayoutSubviews,并检查是否要布置 subview ,因为我们来自ViewController,还是只是常规调用。当我们确定调用确实是因为我们要从ViewController返回时,我们需要隐藏搜索栏(仅当它之前被隐藏时)。

当我们从ViewController返回时,在viewDidLayoutSubviews中对TableViewController进行了三个调用。我猜第一个是tableView,而且似乎第二个调用是“for”(或者更确切地说是来自)tabBar。第二个是向下移动searchBar的代码。我不知道第三个电话是什么,但我们可以忽略它。

因此,现在我们需要检查viewDidLayoutSubviews内部的三件事:我们需要检查是否从ViewController返回,我们需要在按下pushBar之前检查searchBar是否被隐藏(如果应该现在被隐藏),并且需要检查这是此方法的第二个调用。

首先是第一件事。

TableViewController中,我向头文件(@property BOOL backPush;)文件添加了一个属性.h。现在,我需要从ViewController更改此变量。

ViewController中,我这样输入:

#import "TableViewController"
...
-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if(self.isMovingFromParentViewController)
    {
        if([self.navigationController.topViewController isKindOfClass:[TableViewController class]])
            [((TableViewController*)self.navigationController.topViewController) setBackPush:YES];
    }
}

在上面的代码中,当 View 消失时(即向前,向后,关闭,前进等),我正在检查是否要消失,因为它已从父 View 中删除。如果是(调用后退按钮时是这种情况),则我检查现在-当前的顶部 View Controller 是否为TableViewController类,如果我们返回,也是如此。然后,将属性backPush设置为YES。那是我们唯一需要的ViewController

现在,到TableViewController。我在您的行数旁边添加了一个计数器:
@interface TableViewController () {
    NSInteger _rows;
    int count;
}

这是为了跟踪以后已对viewDidLayoutSubviews进行了多少次调用。我在count = 0;中设置了viewDidLoad

现在开始魔术:
-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    if((self.backPush && count == 0 && self.tableView.contentOffset.y ==
                    self.tableView.tableHeaderView.frame.size.height) ||
                    (self.backPush && count == 1 &&
                    self.tableView.contentOffset.y == 0))
    {
        if(count == 0)
            count++;
        else
        {
            count = 0;
            self.backPush = NO;
            [self hideSearchBar];
        }
    }
    else if((count == 0 || count == 1) || self.tableView.tableHeaderView.isFirstResponder)
    {
        count = 0;

        self.backPush = NO;
    }
}

第一个if语句需要以下两种情况之一:
  • backPushYEScount0,并且searchBar已经隐藏。
  • backPushYEScount1,并且searchBar是可见的。

  • 如果1为true,那么我们将count加1。
    如果2.是true,则1.已经发生,现在我们知道从 VC 返回时,我们处于viewDidLayout..的第二轮,并且searchBar WAS 是隐藏的(因为1.发生了),但是现在没有隐藏。它可能发生在 super 方法之类的东西中。
    现在,我们终于可以再次将searchBar推出了。我还重置了count并将backPush设置回NO
    else if也非常重要。它检查count0还是1,或者searchBar是否显示键盘。如果count到达此处时是01,则表示第一个if语句失败,例如searchBar未隐藏或滚动到更高的位置。

    (当我想到它时,else-if应该也检查backPush是否也是YES。现在它反复设置这些变量)

    如果您找到更好的方法,请告诉我!

    关于ios - 如果按下的 Controller 隐藏了标签栏,则UISearchBar会跳转,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22232538/

    10-11 22:47
    查看更多