【问题标题】:Why is this UISearchBar getting resized?为什么这个 UISearchBar 会被调整大小?
【发布时间】:2014-02-20 14:26:07
【问题描述】:

如下所示,当我点击搜索字段时,我的UISearchBar 正在调整大小。它的动画很好地覆盖了导航栏,然后弹出……它缩小了。

设置

UISearchBar 位于原版UIView 中,设置为tableHeaderView。我正在使用UIView(而不是将UISearchBar 设置为标题),因为我想在标题中添加其他视图。

视图在 XIB 文件中定义,UISearchBar 锚定到其所有边框。约束似乎无关紧要。如果我删除它们,会发生同样的问题。

实验

在 Reveal 中检查视图层次结构告诉我,UIView 的大小正确,UISearchBar 的宽度为 1 (?!) 当这种情况发生时

作为一个实验,我将UISearchBar 子类化并让intrinsicContentSize 返回{320,44}。有了这个UISearchBar 可以正确显示,但是当我按下取消时,我得到了以下异常:

 *** Assertion failure in -[UITableView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2903.23/UIView.m:8540
 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'

解决方法

如果我通过代码创建所有内容,它就可以工作。

_headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
searchBar.delegate = self;
[_headerView addSubview:searchBar];

_searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
_searchDisplayController.searchResultsDelegate = self;
_searchDisplayController.searchResultsDataSource = self;
_searchDisplayController.delegate = self;

_tableView.tableViewHeader = _headerView;

这里发生了什么?我显然不会再使用 nib 来处理 UISearchBar 了,但我还是想了解到底发生了什么。

【问题讨论】:

  • 看起来可能有一个自动布局约束来将取消按钮和搜索字段设置为相同的大小。
  • @nhgrif 如果有,我肯定没加。
  • 这就是为什么我将所有内容都放在代码中......

标签: ios iphone uitableview ios7 uisearchbar


【解决方案1】:

区别在于搜索栏的值translatesAutoresizingMaskIntoConstraints。对于基于 XIB 的视图默认为 NO,对于基于代码的视图默认为 YES。显然,搜索控制器假定值为 YES,并且在移植搜索栏时没有设置任何显式约束。

在代码中将值设置为 YES 应该可以修复它(在本地验证)。

更新

如 cmets 中所述,即使使用 translatesAutoresizingMaskIntoConstraints = YES,控制器也不会在取消时将标题视图恢复到其原始状态。但似乎确实有一种解决方法。您可以在标题视图中创建一个出口并在searchDisplayControllerDidEndSearch 中自行恢复它。我做了一个粗略的概念验证(并更新了我的示例项目):

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
    self.tableView.tableHeaderView = self.headerView;
    [self.searchBar removeFromSuperview];
    self.searchBar.frame = CGRectMake(0, 20, 320, 44);
    [self.headerView addSubview:self.searchBar];
}

【讨论】:

  • 我发布的代码中没有自动调整大小的掩码,它也可以工作。
  • 是的,但是UIViewAutoresizingNone 的默认值仍然是一个值。它的意思是“不要调整大小”,可以翻译成等效的约束。但不要相信我的话,试试这个sample project,在viewDidLoad 中有和没有self.searchBar.translatesAutoresizingMaskIntoConstraints = YES
  • 所以我的示例项目没有说服你?
  • 谢谢蒂莫西。看起来这是一个错误,不是吗?使用 IB 时不需要使用translatesAutoresizingMaskIntoConstraints
  • 无疑是一个错误。我向 Apple 提交了一些错误报告。第二个错误是(至少在我更新的示例项目中),即使使用translatesAutoresizingMaskIntoConstraints = YES,点击取消后原始布局也不会恢复。似乎UISearchDisplayController 做了一个未记录的假设,即搜索栏是标题视图的唯一内容。
【解决方案2】:

根据@TimothyMoose 和@hpique 所说的关于设置translatesAutoresizingMaskIntoConstraints = YES (yuck)

在我的代码中,我发现如果我执行以下操作来显示 searchDisplayController

self.searchDisplayController.searchBar.translatesAutoresizingMaskIntoConstraints = YES
[self.searchDisplayController setActive:YES animated:YES] 

关闭 searchDisplayController 时反之,

self.searchDisplayController.searchBar.translatesAutoresizingMaskIntoConstraints = NO
[self.searchDisplayController setActive:NO animated:YES] 

然后我的观点不变(一切都回到我的预期)

如果我关闭时不要调用以下行

self.searchDisplayController.searchBar.translatesAutoresizingMaskIntoConstraints = NO

然后视图搞砸了。

我认为这样做的原因是 NSAutoresizingMaskLayoutConstraint 正在断言它们自己,并且由于它们是约束列表中的最后一个,因此布局引擎会制动真正的约束以满足不需要的 NSAutoresizingMaskLayoutConstraint 约束。

【讨论】:

  • 这似乎可以在 iOS8 beta 5 上正常工作,并在 7.1、8 beta 5 上运行 iOS6 中似乎根本没有出现搜索栏... :( - 我相信搜索栏已关闭屏幕
  • 和 iOS6 上的排序(似乎代码库中的其他代码受到干扰)
猜你喜欢
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
  • 2014-10-08
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多