天道酬勤,学无止境

UISearchController: searchBar and scopeBar overlap on first touch event

问题

我正在尝试使用 Apple 最新的 UISearchController 实现一个简单的搜索栏。 但是,如果我使用搜索栏的范围栏来获得过滤器选择,我似乎无法让它正常工作。

范围栏总是显示我可以接受的在启动范围栏始终显示

但在第一次触摸事件中,搜索栏和范围栏重叠。 搜索栏和范围栏折叠

我使用了 Apple 的 TableView 示例代码应用程序,但它没有改变任何东西。

- (void)viewDidLoad {
[super viewDidLoad];

_resultsTableController = [[APLResultsTableController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
self.searchController.searchResultsUpdater = self;
[self.searchController.searchBar sizeToFit];
self.searchController.searchBar.showsScopeBar = YES;
[self.searchController.searchBar setScopeButtonTitles:@[@"First",@"Second"]];
self.tableView.tableHeaderView = self.searchController.searchBar;

// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.resultsTableController.tableView.delegate = self;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO; // default is YES
self.searchController.searchBar.delegate = self; // so we can monitor text changes + others

// Search is now just presenting a view controller. As such, normal view controller
// presentation semantics apply. Namely that presentation will walk up the view controller
// hierarchy until it finds the root view controller or one that defines a presentation context.
//
self.definesPresentationContext = YES;  // know where you want UISearchController to be displayed

}

我也实现了搜索栏的委托方法,但它只是切换了重叠的时间。

有没有人能够使用 iOS 8s UISearchController 并使用 searchBar 的范围栏来实现搜索栏?

提前致谢

回答1

swift 3的更新:

searchController.searchBar.showsScopeBar = false

swift 4的更新:

似乎在 swift 4 和 ios 11 中,搜索栏发生了变化。 使用上面显示的方法,在某些情况下,范围栏将位于搜索栏内。

if #available(iOS 11.0, *) {
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = false
    } else {
        tableView.tableHeaderView = searchController.searchBar
    }

这为我修好了。 如果 ios 10 可用,我使用上面显示的表格。 如果 ios 11 可用,我会更改我的技术并将导航视图控制器设置为搜索控制器。 你会注意到它看起来和 ios 10 上的一模一样

回答2

这似乎是一个已知的缺陷。 有几个 radr 条目,例如 http://www.openradar.me/20702394,它们引用了类似的问题和使用 sizeToFit() 的解决方法

他们建议的解决方法有效,但仅限于在 viewDidLayoutSubviews 中应用时。 即在所有视图都被布置之后。

override func viewDidLayoutSubviews() {
    self.searchController.searchBar.sizeToFit()
}
回答3

我刚刚花了三天时间处理这个问题,浏览了我能找到的所有帖子,最后在 Apple Dev 论坛上找到了解决方案,所以我想我会发布一个更新来帮助下一个遇到这个问题的人。

解决方法是确保属于 UISearchController 的搜索栏上的 showsScopeBar 属性设置为 false,即 Swift 中的UISearchController.searchBar.showsScopeBar = false

问题似乎是 Apple 的设计意图是让showsScopeBar属性与独立搜索栏而不是由 UISearchController 控制的搜索栏一起使用。 不幸的是,这在类文档中没有提到。 我认为糟糕的设计决定,但事实就是如此。

讨论位于以下线程https://devforums.apple.com/thread/235803 (截至 2018-01-26 的死链接)。

祝你好运。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • UISearchController: searchBar and scopeBar overlap on first touch event
    I'm trying to implement a simple search bar using Apple's latest UISearchController. However I can't seem to get it to work correctly if I use the search bar's scope bar to get a filter choice. The scope bar always shows which I could live with but on the very first touch event the search bar and scope bar overlap. I used Apple's TableView sample code app but it didn't change anything. - (void)viewDidLoad { [super viewDidLoad]; _resultsTableController = [[APLResultsTableController alloc] init]; _searchController = [[UISearchController alloc] initWithSearchResultsController:self
  • UISearchController 的搜索栏与第一个 tableview 单元格重叠(UISearchController's search bar overlaps first tableview cell)
    问题 我正在使用UISearchController并且UISearchBar也有一个范围栏。 搜索栏被添加作为一个子视图的UIView -它是上述UItableView 。 我这样做是因为我希望即使滚动 tableview 搜索栏也始终可见。 问题是范围栏与第一个 tableview 单元格重叠 故事板 范围栏与 tableview 单元格重叠 如何防止这种重叠?,我无法在导航栏中显示搜索栏,因为放置在导航栏中的范围栏不会显示。 回答1 这对我有用: 在 tableview 标题中有搜索显示控制器和 SearchBar。 在 TableViewController 中添加heightForHeaderInSection 。 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 44; //I used the 44, the height of SearchBar } 在您的情况下,您还需要添加范围栏高度。 现在它将始终保持基本高度。 回答2 这对我有用: - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
  • UISearchController's search bar overlaps first tableview cell
    I am using UISearchController and the UISearchBar also has a scope bar. The search bar is added as a subview to a UIView which is above the UItableView. I have done it this way since I want the search bar to be always visible even when the tableview is scrolled. The problem is the scopebar overlaps the first tableview cell StoryBoard Scope bar overlapping the tableview cell How can I prevent this overlapping?, I can't display the searchbar in navigationbar since the scopebar when placed in navigation bar does not get displayed.
  • 我如何在iOS 8中使用UISearchBar且UISearchBar在导航栏中并具有作用域按钮的UISearchController?(How do I use UISearchController in iOS 8 where the UISearchBar is in my navigation bar and has scope buttons?)
    问题 我正在尝试使用iOS 8中的新UISearchController ,并将其UISearchBar嵌入到我的UINavigationBar 。 这很容易做到,如下所示: searchController = UISearchController(searchResultsController: nil) searchController.searchResultsUpdater = self searchController.delegate = self searchController.searchBar.delegate = self searchController.dimsBackgroundDuringPresentation = false searchController.hidesNavigationBarDuringPresentation = false navigationItem.titleView = searchController.searchBar 但是当我添加范围按钮时: searchController.searchBar.showsScopeBar = true searchController.searchBar.scopeButtonTitles = ["Posts, Users, Subreddits"]
  • UISearchBarController iOS 11 问题 - SearchBar 和范围按钮重叠(UISearchBarController iOS 11 issue - SearchBar and scope buttons overlap)
    问题 在这里和这里提到。 第一个链接中没有答案。 在第二个链接中,虽然答案不被接受,但苹果开发者论坛的链接出现错误。 在 iOS 11 之前: iOS 11: 注意:相同的设备相同的代码。 此外,这意味着,所有使用此功能的应用程序都必须重新发布? 回答1 添加这些行为我修复了它: override func viewDidLayoutSubviews() { self.searchController.searchBar.sizeToFit() } 回答2 我可以使用以下代码(根据 greg 的回答)在 iOS11 中正确显示初始外观: [self.searchController.searchBar sizeToFit]; if (@available(iOS 11.0, *)) { self.navigationItem.searchController = self.searchController; self.navigationItem.hidesSearchBarWhenScrolling = NO; } else { // Fallback on earlier versions self.tableView.tableHeaderView = self.searchController.searchBar; } 但是,如果应用程序在后台运行
  • Swift 4 - iOS 11 搜索栏范围不会像它应该的那样出现(Swift 4 - iOS 11 Search bar scope won't appear as it should)
    问题 我有一个在 iOS 10 上运行良好且没有任何问题的应用程序,但是对于 iOS 11 和 Xcode Beta 5,我在搜索栏范围上遇到了这个奇怪的问题,范围栏似乎是从底部切下来的。 (所有版本的 Xcode beta 和 iOS 11 都是一样的)如果有人能让我朝着正确的方向发展,我真的很高兴。 谢谢 上面你可以看到我按下汉堡菜单按钮时看到的东西。 这里没问题.. 搜索栏也有一个范围栏,点击时会显示。我没有将它设置为以编程方式显示。但我想这是设置范围按钮标题时的默认行为。 问题: 当我点击搜索栏输入信息时,我会看到上面的屏幕。 在 iOS 10 上我没有问题。 但是现在,对于 iOS 11,无论我做什么,我都无法让它像在 iOS 10 上一样工作。搜索范围栏显示为从底部切下来的。 这就是它在 iOS 10 中的显示方式,我希望它在 iOS 11 中出现。 屏幕的故事板视图 我在这里粘贴相关代码。 class SlideMenuViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UISearchControllerDelegate,UIGestureRecognizerDelegate{ let searchController = UISearchController
  • 使用 UISearchController 时如何过滤 updateSearchResultsForSearchController 中的对象数组?(How to filter object array in updateSearchResultsForSearchController when using UISearchController?)
    问题
  • UISearchController 搜索栏在活动时与第一个单元格重叠(UISearchController search bar overlap first cell when active)
    问题 我正在使用UISearchController在我的 tableview 中搜索数据。 我没有使用表视图控制器。 我想在搜索栏处于活动状态时隐藏导航栏,因此我设置了self.searchController.hidesNavigationBarDuringPresentation = YES; 是的。 但是,当我这样做并想要搜索时,我的活动搜索栏覆盖了第一个单元格的一部分。 被覆盖的部分与状态栏的高度相同。 我尝试了与此类似的其他文章和问题,但没有任何帮助我解决它。 然后我开始玩表格视图标题大小。 我做了这个 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return 20.0f; } 结果是,当我点击搜索栏时,开始搜索的问题不再存在。 但是,当搜索栏未处于活动状态时,搜索栏和第一个单元格之间会出现空白 任何想法如何解决这个问题? 编辑:添加self.automaticallyAdjustsScrollViewInsets = false; 回答1 我设法通过将 RJiryes 答案与滚动到顶部相结合来解决这个问题。 -(void)willPresentSearchController:(UISearchController *
  • UISearchController won't dismiss searchbar and overlap for iOS 8 Swift
    I'm having problem with the UISearchController where if I have text in the searchbar and dismiss the VC it's in, the searchBar won't go away and just remain on screen overlapping everything in other VCs. Then it crashes if you hit the cancel button. Have tried a few solutions on SO but none have worked. :/ self.resultSearchController = ({ let controller = UISearchController(searchResultsController: nil) controller.searchResultsUpdater = self controller.dimsBackgroundDuringPresentation = false controller.hidesNavigationBarDuringPresentation = false controller.searchBar.sizeToFit() controller
  • Swift 4 - iOS 11 Search bar scope won't appear as it should
    I have an app which works nice and without any problems on iOS 10 but with iOS 11 and Xcode Beta 5, I have this strange problem with search bar scope where the scope bar seems like it was cut from the bottom. (It was the same with all versions of Xcode beta and iOS 11) I would really really be glad if someone can put me in the right direction. Thanks Above you can see what I see when I press the hamburger menu button. No problem here.. searchbar also has a scopebar which shows up when clicked on.I did not set it to show up programatically.But I guess this is its default behaviour when scope
  • 当用户点击视图时取消 UISearchBar(Cancel out of UISearchBar when user taps on view)
    问题 当您点击搜索文本框下方和键盘上方时,有谁知道如何从 UISearchBar 中取消(退出 First Responder)? 谁能帮忙发布一些代码来处理这个问题? 谢谢 回答1 我从 iphonedevbook 示例代码项目 04 中得到的另一个想法是使用一个大的透明按钮,该按钮位于所有其他控件的后面,该按钮除了在点击时退出所有第一响应者之外什么都不做。 即如果用户点击任何没有更重要控件的地方——这是直观的行为——搜索栏和键盘就会消失。 回答2 在父视图(UISearchbar)中添加点击手势 [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:searchBar action:@selector(resignFirstResponder)]]; 回答3 我通过使用 UITapGestureRecognizer 实现了这一点: UIGestureRecognizer* cancelGesture; - (void) backgroundTouched:(id)sender { [self.view endEditing:YES]; } #pragma mark - UISearchBarDelegate -(void)searchBarTextDidBeginEditing
  • UISearchController searchBar 框架仅在第一次单击时调整大小(UISearchController searchBar frame only resizes on first click)
    问题 我刚刚在一个普通的 UIViewController 中实现了一个 UISearchController,我有一个奇怪的问题。 我有一个 UIView,它完全适合我希望 UISearchBar 的大小。 在第一次启动视图时,我将我的 UISearchBar 作为子视图添加到这个 UIView。 但是当我启动它时, UISearchBar 不占用其父 UIView 的大小——它只占用整个屏幕的宽度。 如您所见,它与右侧的按钮重叠。 但是一旦我点击搜索栏并取消它,它就会调整到我想要的确切大小。 这里可能是什么问题? 我尝试将 AutoLayout Constraints 从 SearchBar 添加到其父视图,但它似乎没有改变任何东西。 [UIView addSubview:] 不处理这个吗? 回答1 UISearchController 的视图行为确实很奇怪,但有一个简单的解决方法。 使用额外的容器视图把 UISearchController 的视图放在里面将 UISearchController 的视图自动调整大小掩码设置为 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight 将 UISearchController 的框架设置为容器的视图边界 此时 UISearchController
  • 将过滤器按钮添加到 UISearchController(Add filter button to UISearchController)
    问题 我想在UISearchController的searchBar旁边添加一个“过滤器”或“排序”按钮。 我已经尝试将UIButton和搜索searchbar添加到UIView并将其设置为我的UITableView tableView.tableHeaderView这不起作用,因为tableView.tableHeaderView仅在关闭控制器时才设置回UISearchBar 。 这是我希望它看起来如何的示例: 回答1 我可以用几行代码创建一个搜索过滤器。 我希望它有帮助。 *我选择了书签按钮来应用过滤器图标; 因为我已经将取消按钮用于自定义操作。 首先,您必须委托 searchBar 来处理书签按钮单击操作。 然后你应该设置如下属性。 如果要自定义位置(默认位置在右侧),则需要设置PositionAdjustment。 searchController.searchBar.delegate = self searchController.searchBar.showsBookmarkButton = true searchController.searchBar.setImage(UIImage(named: "Sort"), for: .bookmark, state: .normal) // MARK: You may change position of bookmark
  • IOS7:uisearchdisplaycontroller 总是显示范围栏(IOS7 : uisearchdisplaycontroller always show scope bar)
    问题 基本上我想要实现的是让我的范围栏永远不会消失。 环境:IOS 7,故事板,在视图控制器内我有一个“搜索栏和搜索显示控制器”和一个单独的表格视图(搜索栏不在表格内) 在视图 controller.h 里面 @property (nonatomic, strong) IBOutlet UISearchBar *candySearchBar; 在视图 controller.m 里面 @synthesize candySearchBar; 我尝试过的:在自定义搜索栏类中 - (void) setShowsScopeBar:(BOOL) showsScopeBar { if ([self showsScopeBar] != showsScopeBar) { [super invalidateIntrinsicContentSize]; } [super setShowsScopeBar:showsScopeBar]; [super setShowsScopeBar: YES]; // always show! NSLog(@"setShowsScopeBar searchbar"); NSLog(@"%hhd", showsScopeBar); } 和 searchBarDidEndEditing 视图控制器中的相同内容,但随后 - (void)viewDidLoad { [super
  • UISearchController searchBar frame only resizes on first click
    I have just implemented a UISearchController in a regular UIViewController, and I have a kind of weird issue. I have a UIView that is adapted exactly to the size I want my UISearchBar to take. On first launch of the view, I add my UISearchBar as a SubView to this UIView. But when I launch it, the UISearchBar doesn't take the size of its parent UIView -- it just takes the width of the whole screen. As you can see, it overlaps with the button on the right. But once I click on the search bar and cancel it, it resizes to the exact size I want. What could be the issue here? I've tried adding
  • 使用 Swift 标头中的分段控件更改 UICollectionView 的内容(Changing content of UICollectionView with segmented Control in the header in Swift)
    问题 几个小时以来,我试图解决这个问题,但没有找到合适的解决方案。 我想要一个自定义 UICollectionView,在标题中有一个分段控件。 更改分段控制索引应以不同方式呈现单元格。 到目前为止,我可以在我的 collectionView 的标题中显示分段控件,但更改我的 UserSearchHeader 内的 collectionView 的内容不起作用。 我创建了一个名为UserSearchController的自定义 UICollectionView,它是UICollectionView的子类并符合 UICollectionViewDelegateFlowLayout 协议。 class UserSearchController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UISearchBarDelegate { .... 我的自定义 collectionView UserSearchController有一个自定义标题 ( UserSearchHeader ) 和自定义单元格 ( UserSearchCell )。 collectionView?.register(UserSearchCell.self, forCellWithReuseIdentifier: cellId)
  • 如何在嵌入 UINavigationController 的 UISearchController 中添加范围按钮(How to add scope buttons in a UISearchController embedded in UINavigationController)
    问题 我有一个应用程序,它显示嵌入在 UINavigationController 中的 MKMapView。 在 UINavigationController 中,我放置了一个 UISearchController。 当用户触摸 UISearchController 时,它会显示一个 UITableViewController。 当我没有在 UISearchController 中添加 Scope 按钮时,它运行良好。 这是我启动应用程序时 UINavigationController 中 UISearchController 的屏幕截图。 接下来,当我触摸 UISearchController 时,它会显示 UITableViewController 和范围按钮。 在这里我们已经可以看到范围按钮有问题,因为它们没有很好地集成在 UISearchController 中(颜色应该是半透明的) 接下来,当我触摸取消按钮返回主视图控制器时,UISearchController 没有恢复其原始样式 它有一个深灰色边框(可能来自范围按钮)。 这是我在主视图控制器中添加 UISearchController 的方法 func initSearchController() { let mySearchController = UIStoryboard.init(name: "Main"
  • tableHeaderView中的UISearchController searchBar在屏幕外进行动画处理(UISearchController searchBar in tableHeaderView animating out of the screen)
    问题 我有一个UISearchController用UITableViewController作为searchResultsController的UISearchBar如此searchController被设置为在tableHeaderView我目前tableView显示在我的根视图控制器。 几乎一切都按预期进行。 但是在UISearchBar的动画中(当我单击searchBar并隐藏UINavigationBar且searchBar转到顶部时,如UISearchDisplayController ),我有一个奇怪的行为。 它没有跳到UINavigationBar的位置(y:0),而是跳出了屏幕,然后开始显示取消按钮的动画。 我尝试将实例化代码移动到viewDidLoad而不是init ,结果是相同的。 我认为问题的中心在searchResultsController视图的框架中,但是我不确定(我尝试设置框架,但没有成功)。 我正在做的所有事情都是用纯代码编写的。 这是代码的相关部分: - (void) viewDidLoad { [super viewDidLoad]; // search controller setup self.searchController = [[UISearchController alloc]
  • How to add scope buttons in a UISearchController embedded in UINavigationController
    I have an App that is presenting a MKMapView embedded in a UINavigationController. In the UINavigationController I have put a UISearchController. When the User touch the UISearchController it displays a UITableViewController. It works well while I'm not adding the Scope button in the UISearchController. Here the screenshot of the UISearchController in the UINavigationController when I start the App. Next when I touch the UISearchController, it displays the UITableViewController and scope button. Here we can already see there's an issue with the scope button because they are not well integrated
  • 使用 UISegmentedControl 和 UISearchController(Using UISegmentedControl with UISearchController)
    问题 如何将SegmentedControl与UISearchController一起使用? 当SearchBar处于非活动状态时,我需要SegmentedControl位于SearchBar下,并在SearchBar激活时隐藏分段控件。 我将 SearchController.searchBar 放在 tableview 标题中,因此我在故事板中定义的SegmentedControl与SearchBar重叠。 当我尝试通过调用 tableView.tableHeaderView?.addSubview(customSecmentedControl) 在 vi​​ewDidLoad 中以编程方式添加SegmentedControl ,它与 tableView 中的单元格重叠。 回答1 您不必连接自己的分段控件来处理此问题,因为UISearchController已经提供了该功能。 使用搜索栏的scopeButtonTitles属性来设置范围栏的标题: searchController.searchBar.scopeButtonTitles = ["Small", "Medium", "Large"] 您可以通过访问搜索栏的selectedScopeButtonIndex属性来确定选定的范围。 当范围发生变化时,搜索栏会发送其委托通知: func searchBar(_