如果按下的控制器隐藏了标签栏,则UISearchBar会跳转 [英] UISearchBar jumps if pushed controller hides the tab bar

查看:45
本文介绍了如果按下的控制器隐藏了标签栏,则UISearchBar会跳转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的UI结构如下:

UITabBarController ( TBC )-> UINavigationController ( NC )-> UITableViewController ( TVC )

UITabBarController (TBC) -> UINavigationController (NC) -> UITableViewController (TVC)

(为简单起见,假设 TBC viewControllers 数组中只有一个控制器- NC )

(for the simplicity of the example lets say the TBC has only one controller on its viewControllers array - the NC)

我的 TVC 具有 UISearchBar 作为其表头,当出现 TVC 时,我将搜索栏隐藏在 NC 导航栏,方法是设置表格视图的内容偏移量.

My TVC has UISearchBar as its table header, and when the TVC appear I hide the search bar beneath the NC navigation bar by settings the table view content offset.

当用户点击 TVC 中的单元格时,将推另一个视图控制器( VC ),并使用 VC.hidesBottomBarWhenPushed = YES隐藏标签栏;

When user tap a cell in the TVC another view controller is pushed (VC) and hides the tab bar with VC.hidesBottomBarWhenPushed = YES;

现在有一种非常令人讨厌的行为,我不知道该如何解决:
当用户将 VC 中的后退按钮点击回到 TVC 时,即使在之前被隐藏(位于导航栏下方),搜索栏也会跳转为可见.VC 已推送.

Now there is a very annoying behavior that I dont know how to solve:
When the user tap the back button from VC back to TVC, the search bar jumps to be visible even if it was hidden (beneath the navigation bar) before the VC was pushed.

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

This effect happens only if the TVC doesn't have enough rows to fill the screen, its like the search bar force itself to be visible if there is a place on screen. but its really looks bad and buggy.

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

I uploaded a simple project that demonstrates the problem, it has the same structure as I described in my question.
I added two bar buttons for your convenience, the "hide bar" button hides the search bar for you, and the "toggle count" button toggle the table view rows count to demonstrate that the issue happens only if there are few items.

推荐答案

好的..在我看来,您偶然发现了一个错误.应该通过apples bugreporter(此处)进行报告.

Okay.. It looks to me like you've stumbled upon a bug. It should be reported through apples bugreporter (here).

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

I've made a fairy simple working work-around, but keep in mind that it is a work-around. This will work, but you might have to review it if you have/add other controls to the tableView. It should be safe to use(not acting randomly), and it's not the ugliest of work-arounds, so I think it's fine to use in a release. I've uploaded the same project with the fix here, and you can just go ahead and download it, and you'll probably understand what I've done. I'll explain (in extreme detail) what I've actually thought and done here, in case the download links dies in the future:

思路:

就像simalone所说的那样,问题在于,当 hidesBottomBarWhenPushed 设置为 YES 时,它将调用一个附加的 viewDidLayoutSubviews ,该重置会以某种方式重置您当前的状态.我们需要覆盖 viewDidLayoutSubviews ,并检查是否要布局子视图,因为是来自 ViewController ,还是只是常规调用.当我们确定调用确实是因为我们要从 ViewController 返回时,我们需要隐藏搜索栏(仅在之前已隐藏的情况下).

As simalone also said, the problem is that when hidesBottomBarWhenPushed is set to YES, then it will call an additional viewDidLayoutSubviews which somehow resets your current state. We need to override viewDidLayoutSubviews, and check if we are laying out subviews because we are coming from ViewController, or if it's just a regular call. When we establish that the call is indeed because we are returning from ViewController, we need to hide the search bar (only if it was hidden before).

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

When we return from ViewController, three calls are made to viewDidLayoutSubviews in TableViewController. I'm guessing the first is for tableView, and it seems that the second call is 'for'(or rather from) the tabBar. This second one is the one moving the searchBar down. I have no idea what the third call is, but we can ignore it.

因此,现在我们需要在 viewDidLayoutSubviews 中检查三件事:我们需要检查是否从 ViewController 返回,我们需要检查searchBar是否被隐藏在我们推送(如果它应该现在被隐藏)之前,我们需要检查是否是对该方法的第二调用.

So now there are three things we need to check inside viewDidLayoutSubviews: We need to check if we are returning from ViewController, we need to check if the searchBar was hidden before we pushed(if it should hidden be now), and we need to check that it's the second call to this method.

第一件事.

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

In TableViewController, I added a property @property BOOL backPush; to the header(.h)-file. Now I need to change this variable from ViewController.

ViewController 中,我输入以下内容:

In ViewController, I put this:

#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];
    }
}

在上面的代码中,当视图消失时(即,向前,向后,关闭等),我正在检查是否要消失,因为它已从父级中删除.如果是(调用后退按钮时是这种情况),我检查当前的 now 顶视图控制器是否为 TableViewController 类,如果是,则为我们回去.然后,将属性 backPush 设置为 YES .那是我们在 ViewController 中唯一需要的东西.

In the code above, when the view is disappearing (I.E pushing forward, back, closing, whatever), I'm checking if we are disappearing because it was removed from the parent. If it is(which it is when the back-button is called), I check if the now-current top view controller is of class TableViewController, which it also is if we go back. Then I set the property backPush to YES. That's the only thing we need in ViewController.

现在,转到 TableViewController .我在您的行数旁边添加了计数器:

Now, to the TableViewController. I added a counter next to your row-count:

@interface TableViewController () {
    NSInteger _rows;
    int count;
}

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

This is to keep track of how many calls have been made to viewDidLayoutSubviews later. I set count = 0; in 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语句需要以下两种情况之一:

The first if-statement wants either of these situations:

  1. backPush YES count 0 ,并且searchBar已隐藏.
  2. backPush YES count 1 ,并且searchBar是可见的.
  1. backPush is YES, count is 0, and searchBar is already hidden.
  2. backPush is YES, count is 1, and searchBar is visible.

如果1为true,则我们将 count 递增1.如果2.是true,那么1.已经发生,现在我们从 VC 返回时,我们已经进入第二轮 viewDidLayout.searchBar WAS 是隐藏的(因为1.发生了),但现在并未隐藏.它可能发生在超级方法之类的东西中.现在,我们终于可以再次将searchBar推出了.我还重置了计数并将backPush设置回 NO .

If 1. is true, then we increment count by 1. If 2. is true, then 1. has already happened, and we now know that we are in the second round of viewDidLayout.. when we are coming back from VC AND that the searchBar WAS hidden (because 1. happened) but now isn't hidden. It probably happens in the super-method or something. Now we can finally push the searchBar out again. I also reset count and set backPush back to NO.

else if 也很重要.它检查 count 0 还是 1 ,或者searchBar是否显示键盘.如果count到达此处时是 0 1 ,则表示第一个if语句失败,例如,searchBar未隐藏或滚动到很远向上.

The else if is also pretty important. It checks if count is 0 or 1, or if the searchBar has the keyboard showing. If count is 0 or 1 when it reaches here, it means that the first if-statement failed, e.g that the searchBar wasn't hidden, or that it was scrolled far up.

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

(When I think of it, the else-if should check if backPush is YES as well. Now it sets those variables repeatedly)

让我知道您是否找到更好的方法!

Let me know if you find a better way!

这篇关于如果按下的控制器隐藏了标签栏,则UISearchBar会跳转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆