天道酬勤,学无止境

How to dismiss a ViewController while the navigationItem's searchBar has focus

I updated my app to handle the new iOS 11 search behavior for search bars under the navigation bar:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
    self.navigationItem.searchController = searchController;

    // Those are optional, but that's what I want my UI to look like
    searchController.hidesNavigationBarDuringPresentation = NO;
    searchController.obscuresBackgroundDuringPresentation = NO;
    self.navigationItem.hidesSearchBarWhenScrolling = NO;
}

I also have a button on my view, which when tapped will dismiss the current view controller:

- (IBAction)dismiss:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

The problem is: if the searchController's searchBar has focus (ie. is the first responder) when the user taps the button, the view controller is not dismissed.

  • On the first tap on the button, the searchBar loses its focus and the keyboard hides (as if [searchBar resignFirstResponder] had been called);
  • On the second tap, the view controller is finally being dismissed.

How can I make the first tap on the button dismiss the view controller immediately (removing the searchBar's focus as a side effect)?

评论

The solution to dismiss the view controller immediately is to use the UISearchController isActive property:

- (IBAction)dismiss:(id)sender
{
    self.navigationItem.searchController.active = NO;
    [self dismissViewControllerAnimated:YES completion:nil];
}

In my scenario I have a UITableViewController with a search bar as overlay. The search results are in a separate UITableViewController. Now I wanted to dismiss the overlay while the search results are shown. @Guillaume Algis your solution worked perfectly for me as well.

Syntax in Swift 4:

    self.navigationItem.searchController?.isActive = false
    self.dismiss(animated: true) {}

Swift 4.2

self.searchController.dismiss(animated: false, completion: nil)
self.dismiss(animated: true, completion: {
   ///
})

In my case, work around is:

UIView.setAnimationsEnabled(false)
searchController.isActive = false
UIView.setAnimationsEnabled(true)

then you can dismiss viewController by delegate or directly.

All the above methods cause updateSearchResults to be called with an empty string.
Depending on your implementation this may lead to reloading of the tableview which may be detrimental to the user experience.

The following works around this issue for me:

self.presentingViewController?.dismiss(animated: true, completion: nil)

受限制的 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>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • UISearchBar在iOS 11中增加导航栏的高度(UISearchBar increases navigation bar height in iOS 11)
    问题 我的UISearchBar是导航栏的一部分,例如: let searchBar = UISearchBar() //some more configuration to the search bar ..... navigationItem.titleView = searchBar 更新到iOS 11后,我的应用程序中的搜索栏发生了一些奇怪的事情。 在iOS 10及iOS 10 ,我的导航栏如下所示: 现在使用iOS 11我可以: 如您所见,两个搜索栏的舍入存在差异,这并不困扰我。 问题是搜索栏增加了导航栏的高度。 因此,当我转到另一个控制器时,它看起来也很奇怪: 实际上,奇怪的黑线的高度加上当前导航栏的高度等于第二张图片中显示的导航栏的高度... 任何想法如何摆脱黑线,并在所有视图控制器中具有一致的导航栏高度? 回答1 在两种情况下,iOS 11的NavigationBar和SearchBar下出现黑线: 当我使用UISearchBar 0从ViewController推送另一个ViewControllers时当我通过UISearchBar以“拖动权以关闭”来关闭ViewController时 我的解决方案是:使用UISearchBar将此代码添加到ViewController中: -(void)viewWillDisappear:(BOOL)animated{
  • 无法将searchBar设置为firstResponder(Cannot set searchBar as firstResponder)
    问题 我有一个在tableviewcontroller中设置的searchBar。 我已经引用了这个类似的问题,在UITableView确实重新出现后,UISearchBar不能成为第一响应者,但是仍然无法将其设置为第一响应者。 在.h文件中: @property (strong, nonatomic) UISearchController *searchController; @property (strong, nonatomic) IBOutlet UISearchBar *searchBar; 鉴于didload: self.searchController = [[UISearchController alloc]initWithSearchResultsController:nil]; self.searchController.searchResultsUpdater = self; self.searchController.dimsBackgroundDuringPresentation = NO; self.searchController.hidesNavigationBarDuringPresentation = NO; self.searchController.searchBar.frame = CGRectMake(self
  • 嵌入到NavigationItem中的破碎的UISearchBar动画(Broken UISearchBar animation embedded in NavigationItem)
    问题 我将搜索栏添加到导航项的新方法遇到问题。 如下图所示,有两个UIViewController,一个接一个,两个都有搜索栏。 问题是动画,当搜索栏在第一个视图控制器上可见而不在第二个视图控制器上可见时,动画很难看。 搜索栏占据的区域停留在屏幕上,然后突然消失。 该代码非常基础(项目中未进行其他任何更改): (我主要使用C#编写,因此此代码中可能存在错误。) ViewController.swift: import UIKit class ViewController: UITableViewController, UISearchResultsUpdating { override func loadView() { super.loadView() definesPresentationContext = true; navigationController?.navigationBar.prefersLargeTitles = true; navigationItem.largeTitleDisplayMode = .automatic; navigationItem.title = "VC" tableView.insetsContentViewsToSafeArea = true; tableView.dataSource = self; refreshControl
  • UIViewController 中的 UISearchController(UISearchController in a UIViewController)
    问题 我希望在 Swift 中创建与 Apple 地图应用程序类似的功能。 无论如何将 UISearchController 集成到常规视图中(即:不是 UITableView)。 在连接的搜索栏内单击后,通过 Storyboard 放入一个会导致崩溃。 或者有什么方法可以用 UITableView 实现这个结果? 回答1 我在情节提要的视图控制器中添加了一个搜索栏和搜索显示控制器。 视图控制器仅包含搜索栏和搜索显示控制器,并没有自己的 TableView。 当您在视图控制器中添加搜索栏时,它会自动将您的视图控制器设置为委托。 现在,搜索栏和搜索显示控制器有一个自己的表格视图,当您在框内单击并开始输入时,它会使用它来显示搜索结果。 这个表视图需要你的视图控制器提供 numberOfRowsInSection 和 cellForRowAtIndexPath 函数的实现,以便它正确显示数据。 当你在没有这些的情况下运行你的项目并在搜索栏中点击时,你会得到以下错误:- tableView:numberOfRowsInSection:]: 无法识别的选择器发送到实例 0x7fbf63449660 *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序 如果您看到,错误出在 numberOfRowsInSection 方法上。 更改您的视图控制器定义
  • 如何设置动画在UINavigationBar的顶部添加UISearchBar(How to animate add UISearchBar on top of UINavigationBar)
    问题 如果我在viewDidLoad设置了displaysSearchBarInNavigationBar = YES ,则视图显示时搜索栏将位于导航栏中。 但是我想在触摸栏按钮项时在导航栏顶部显示搜索栏。 就像下面的图片 普通导航栏: 单击右栏按钮后单击导航栏顶部的搜索栏 回答1 我对Mark的答案做了一些修改,以使其能够在IOS 8中快速运行。 class ViewController : UIViewController, UISearchBarDelegate { var searchBar = UISearchBar() var searchBarButtonItem: UIBarButtonItem? var logoImageView : UIImageView! override func viewDidLoad() { super.viewDidLoad() // Can replace logoImageView for titleLabel of navbar let logoImage = UIImage(named: "logo-navbar")! logoImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: logoImage.size.width, height: logoImage.size
  • 尝试在取消分配时加载视图控制器的视图…UISearchController(Attempting to load the view of a view controller while it is deallocating… UISearchController)
    问题 我有UISearchController' in my UIVIew's viewDidLoad`中创建UISearchController' in my UIVIew's代码。 self.resultSearchController = ({ let controller = UISearchController(searchResultsController: nil) controller.searchResultsUpdater = self controller.searchBar.delegate = self controller.dimsBackgroundDuringPresentation = false controller.searchBar.sizeToFit() controller.hidesNavigationBarDuringPresentation = false //prevent search bar from moving controller.searchBar.placeholder = "Search for song" self.myTableView.tableHeaderView = controller.searchBar return controller })() 关闭完成后,控制台中将立即显示以下警告:
  • 在Swift的导航栏中获取搜索栏(Get search bar in navigation bar in Swift)
    问题 因此,我尝试了所有尝试使搜索栏进入Swift导航栏的尝试。 但是可悲的是我还没有开始工作... 对于那些不知道我在说什么的人,我正在尝试做这样的事情 请注意导航栏中的搜索栏。 所以这是我目前正在使用的 self.searchDisplayController?.displaysSearchBarInNavigationBar = true 我将其弹出到viewDidLoad ,然后在加载与我一起出现的应用程序时,只是一个空的导航栏.... :(有什么想法吗? 回答1 试试这个 let leftNavBarButton = UIBarButtonItem(customView:Yoursearchbar) self.navigationItem.leftBarButtonItem = leftNavBarButton 更新 您保留了一个懒惰的UISearchBar属性 lazy var searchBar:UISearchBar = UISearchBar(frame: CGRectMake(0, 0, 200, 20)) 在viewDidLoad中 searchBar.placeholder = "Your placeholder" var leftNavBarButton = UIBarButtonItem(customView:searchBar) self
  • Google自动完成教程将api迅速化(Tutorial for Google autocomplete places api for swift)
    问题 我想拥有一个自动填充文本字段,该文本字段可以像我的android那样自动填充位置: https://developers.google.com/places/training/autocomplete-android 有谁知道我在哪里可以找到本教程或示例的教程? 谢谢! 回答1 脚步 : 在您的快速项目中添加Alamofire CocoaPods。 在Google API控制台上找到您的Google Place API密钥。 添加以下代码 ViewController.swift import UIKit class ViewController: UIViewController { override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) let gpaViewController = GooglePlacesAutocomplete( apiKey: "YOUR GOOGLE PLACE API KEY", placeType: .Address ) gpaViewController.placeDelegate = self presentViewController(gpaViewController, animated: true, completion: nil) }
  • 如何在单击“取消”按钮时退出搜索?(How to exit from the search on clicking on Cancel button?)
    问题 我有一个带有取消按钮的搜索栏。 但是当我点击取消按钮时,它不会关闭搜索栏。 我怎样才能在单击“取消”时将搜索栏返回到第一个状态? 如果您有任何问题 - 请问我 回答1 您需要实现 UISearchBarDelegate : class ViewController: UIViewController, UISearchBarDelegate { @IBOutlet weak var searchBar: UISearchBar! 将搜索栏委托设置为 self override func viewDidLoad() { super.viewDidLoad() searchBar.showsCancelButton = true searchBar.delegate = self 然后实现 butCancelSearchAction 委托函数以执行您需要执行的任何操作来取消搜索操作并重置搜索文本: func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { // Do some search stuff } func searchBarCancelButtonClicked(searchBar: UISearchBar) { // Stop doing the search stuff //
  • 防止UISearchDisplayController隐藏导航栏(Prevent a UISearchDisplayController from hiding the navigation bar)
    问题 每当用户开始编辑UISearchDisplayController的搜索栏时,搜索控制器将变为活动状态,并在显示搜索表视图时隐藏视图的导航栏。 是否可以防止UISearchDisplayController隐藏导航栏而不重新实现它? 回答1 iOS 8引入的新UISearchController类具有属性hidesNavigationBarDuringPresentation ,如果您想保持导航栏可见,则可以将其设置为false(默认情况下仍将隐藏)。 回答2 我只是对UISearchDisplayController进行了一些调试,发现它正在UINavigationController上调用私有方法来隐藏导航栏。 这发生在-setActive:animated:中。 如果您将UISearchDisplayController子类化,并使用以下代码覆盖此方法,则可以通过伪装已经隐藏的NavigationBar来防止其被隐藏。 - (void)setActive:(BOOL)visible animated:(BOOL)animated; { if(self.active == visible) return; [self.searchContentsController.navigationController setNavigationBarHidden:YES
  • iOS 11 SearchBar in NavigationBar
    With iOS 11 Apple has redesigned the UISearchBar by making the corners rounder and the height bigger. Adding a UISearchBar to the navigationBar is pretty simple by just setting it as the titleView of the navigationItem using navigationItem.titleView = searchBar. However, in iOS 11 it does not seem to work anymore as expected. Have a look at the screens where we compare the same setup using iOS 10 and iOS 11 iOS 10 iOS 11 You can clearly see that the SearchBar increases the size of the NavigationBar but the bar buttons do not get aligned correctly. Also the searchBar does not use the available
  • 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
  • 如何在 UINavigationBar 中添加 UISegmentedControl?(How to add the UISegmentedControl in UINavigationBar?)
    问题 我试图将UISegmentedControl添加到带有标题的UINavigationBar底部。 但我不能添加它,我不能添加UISegmentedControl在tableView.headerView ,因为我需要在搜索栏tableView.headerView ,所以只有一个解决方案,我需要添加UISegmentedControl至底部UINavigationBar 。 有人有其他想法我可以解决这种情况吗? 这是我尝试过的代码(使用Swift ): class searchingViewController: UITableViewController{ override func viewDidLoad() { var items: [AnyObject] = ["Searching Method A", "Searching Method B"] var searchSC:UISegmentedControl! searchSC.frame = CGRectMake(0, 0, frame.width - 20, 30) searchSC.selectedSegmentIndex = 1 searchSC.backgroundColor = UIColor(white: 1, alpha: 1) searchSC.layer.cornerRadius = 5.0
  • 如何在嵌入 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"
  • 键盘关闭后,如何保持搜索栏中的“取消”按钮处于启用状态?(How do you keep the cancel button in the search bar enabled when the keyboard is dismissed?)
    问题 我正在尝试实现与Apple的“通讯录”应用相同的效果(左图)。 即使关闭键盘,也可以启用UISearchBar中的“取消”按钮。 我的应用程序的行为有所不同(正确的屏幕截图)。 取消键盘后,取消按钮将自动变为禁用状态。 用户被迫一次点击取消按钮以启用它,然后再次点击以实际触发关闭。 这不是良好的用户体验。 我将如何像Apple的“通讯录”应用一样始终使取消按钮保持启用状态? 技术细节: 由于某些设计要求,我不使用UISearchDisplayController 。 这只是一个带有我自己的自定义搜索控制器的UISearchBar 。 使用[self.searchBar showsCancelButton:YES animated:YES]显示取消按钮。 使用[self.searchBar resignFirstResponder]关闭键盘。 回答1 调用[self.searchBar resignFirstResponder]将禁用取消按钮。 因此,您应始终在调用后更新“取消”按钮以将其启用。 物镜 [searchBar resignFirstResponder]; UIButton *cancelButton = (UIButton *)[searchBar valueForKey:@"cancelButton"]; [cancelButton setEnabled:YES
  • UISearchbar clearButton强制键盘出现(UISearchbar clearButton forces the keyboard to appear)
    问题 我有一个UISearchBar,它充当表格视图的实时过滤器。 通过endEditing:关闭键盘后,查询文本和灰色的圆形“清除”按钮仍然保留。 从这里开始,如果我点击灰色的“清除”按钮,则键盘将在清除文本时再次出现。 我该如何预防? 如果键盘当前未打开,我希望该按钮清除文本而无需重新打开键盘。 当我点击清除按钮时,有一个协议方法被调用。 但是向UISearchBar发送resignFirstResponder消息对键盘没有任何影响。 回答1 这是一个古老的问题,我遇到了同样的问题,并设法通过以下方式解决了这个问题: 由于用户点击“清除”按钮而调用UISearchBarDelegate的searchBar:textDidChange:方法时,searchBar尚未成为第一响应者,因此我们可以利用它来检测用户实际上何时旨在清除搜索,而不是将焦点放在searchBar和/或执行其他操作。 为了跟踪这一点,我们需要在viewController中声明一个BOOL ivar,它也是searchBar委托(我们将其shouldBeginEditing ),并将其设置为初始值为YES (假设我们的viewController类称为SearchViewController): @interface SearchViewController : UIViewController
  • Swift 中的 TableView 搜索(TableView search in Swift)
    问题 我有两个数组:FirstTableArray(包括品牌名称)和 SecondTableArray(包括模型)。 我想添加搜索,通过它可以通过名称的一部分找到手机型号。 import UIKit import MessageUI class FirstTableViewController: UITableViewController { var FirstTableArray = [String]() var SecondTableArray = [SecondTable]() override func viewDidLoad() { super.viewDidLoad() self.navigationController?.navigationBar.isTranslucent = false self.navigationController?.navigationBar.barStyle = .black self.navigationController?.navigationBar.tintColor = UIColor.white // First Table Array FirstTableArray = ["Apple", "Samsung"] // Second Table Array SecondTableArray = [ SecondTable
  • 在iOS 8的导航栏中显示搜索栏(Displaying search bar in navigation bar in iOS 8)
    问题 UISearchDisplayController具有一个名为displaysSearchBarInNavigationBar的boolean属性。 在iOS 8中将搜索栏移到那里相当于什么? 任何指导,不胜感激。 这是我的代码,我不完全确定为什么这不起作用。 当我单击搜索栏时,它只是消失而不是将自身和导航栏向上移动。 import UIKit class ViewController: UIViewController, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource { let searchController = UISearchController(searchResultsController: nil) var tableView = UITableView() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.searchController
  • 如何在 Xamarin Forms 的 NavigationBar 中包含视图?(How to include view in NavigationBar of Xamarin Forms?)
    问题 我需要你的帮助 ! 我从事跨平台的移动开发项目。 我将 Visual Studio 与 Xamarin Forms 一起使用。 我有一个 SearchBar(Xamarin.Forms 类),但是,我的问题是将它包含在 NavigationBar 中。 目前,我有一个 MasterDetailPage,我用 new NavigationPage(new customPage()) 初始化 this.Detail。 我也有一个 SearchBar 渲染器。 所以,我需要原始的 NavigationBar(我想保留返回按钮)但我想在里面添加我的 SearchBar。 如果您知道一种特别是对 android 执行此操作的方法,我将不胜感激。 先感谢您 ! 回答1 您需要创建自定义NavigationRenderer并将您自己的UISearchBar插入UIToolbar或SearchView插入ViewGroup : Xamarin Forms:渲染器基类和本机控件 作为通过自定义NavigationRenderer将 iOS UISearchBar插入导航栏的示例: 注意:为了保持解耦,使用MessagingCenter允许您在自定义渲染器中没有任何硬编码事件依赖性的情况下泵送消息。 [assembly:ExportRenderer (typeof(NavigationPage)
  • 将 UITextField 添加到导航项的标题视图(Add UITextField to title view of navigation item)
    问题 如何将文本字段添加到导航项的标题视图并使其大小正确? 如果我用这样的搜索栏来做这件事,它工作正常,但我不知道如何让文本字段以与搜索栏相同的方式调整自身大小。 myViewController.navigationItem.titleView = [UISearchBar new]; 回答1 正如我的评论所建议的,请尝试以下操作,在我看来这就是您所追求的。 UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(0, 0, self.navigationController.navigationBar.frame.size.width, 21.0)]; self.navigationItem.titleView = textField; [textField becomeFirstResponder]; 回答2 Class: ViewController: UISearchBarDelegate { let searchController = UISearchController(searchResultsController: nil) navigationItem.searchController = searchController navigationItem