【问题标题】:Get search bar in navigation bar in Swift在 Swift 的导航栏中获取搜索栏
【发布时间】:2014-11-04 01:57:11
【问题描述】:

所以我已经尝试了所有尝试将搜索栏放入 Swift 导航栏中的方法。但遗憾的是,我还没有让它工作,只是还......

对于那些不知道我在说什么的人,我正在尝试做这样的事情

注意导航栏中的搜索栏。所以这就是我目前正在使用的

self.searchDisplayController?.displaysSearchBarInNavigationBar = true

我在viewDidLoad 中弹出了它,然后当我加载我看到的应用程序时,只是一个空的导航栏.... :( 有什么想法吗?

【问题讨论】:

    标签: ios xcode swift uinavigationbar uisearchbar


    【解决方案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.navigationItem.leftBarButtonItem = leftNavBarButton
    

    如果你想使用故事板 只需将您的搜索栏拖动为插座,然后用您的插座搜索栏替换惰性属性

    【讨论】:

    • 如何识别Yoursearchbar
    • 到目前为止一切顺利。但是我将如何添加占位符?有什么办法通过故事板?
    • 你只需更改搜索栏的属性添加一个占位符。我更新答案
    • 嗨,你能告诉我整个代码吗?我不太了解lazy 部分
    • 谁能解释一下lazy是做什么的?懒惰的 var searchBar 与 var searchBar 有什么区别
    【解决方案2】:
        // create the search bar programatically since you won't be
        // able to drag one onto the navigation bar
        searchBar = UISearchBar()
        searchBar.sizeToFit()
    
        // the UIViewController comes with a navigationItem property
        // this will automatically be initialized for you if when the
        // view controller is added to a navigation controller's stack
        // you just need to set the titleView to be the search bar
        navigationItem.titleView = searchBar
    

    【讨论】:

    【解决方案3】:

    Swift 5、XCode 11、Storyboard 方式,因此您可以通过 storyboard 轻松添加所有搜索栏属性,并且您的视图控制器类中有 less code

    1.) 将您的搜索栏视图添加为视图控制器中的外部视图。

    2.) 将 searchBarView 连接到您的视图控制器。

    3.) 将您的 searchBarView 添加到您的导航栏标题项。

    navigationItem.titleView = searchBarView
    

    结果:

    【讨论】:

    • 我希望我能更多地支持这个。我不知道你能做到这一点!
    • @Egzon 这个正在将导航栏的大小从 44 更改为 56。因此,当我返回上一个视图控制器时,导航控制器的闪烁会更新到其原始大小 44。关于它的任何建议请。
    • 嗨@MiteshDobareeya,我会在下周检查有什么问题并回复你。您是否在同一个 UINavigationViewController 中推送视图控制器?
    • @EgzonP。是的,我将它推入同一个 UINavigationViewController。主根视图控制器导航栏的大小完美为 44。当我推动第二个视图控制器并添加搜索栏时,导航栏到第二个 vc 的大小增加到 56。所以当我弹出到第一个 vc 时,它的导航栏得到眨眼。
    【解决方案4】:

    在您的视图控制器中:

    lazy var searchBar = UISearchBar(frame: CGRectZero)
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        searchBar.placeholder = "Search"
    
        navigationItem.titleView = searchBar
    }
    

    这样做,通过设置navigationItem.titleView,搜索栏在iPhone 和iPad 设备上自动居中。注意:仅在 v8.4 和 v9.0 上测试过

    适用于 SWIFT 3

    lazy var searchBar = UISearchBar(frame: CGRect.zero)
    

    【讨论】:

    • 当用户点击“取消”按钮时,如何将其从 navigationItem.titleView 中移除?
    • 同样的问题 ^
    • 如果你说的是搜索栏的取消按钮,那我就别想了。实现 UISearchBarDelegate 函数 searchBarCancelButtonClicked(:),在该函数中调用 navigationItem.titleView = nil。如果这就是您所说的“删除它”,这应该删除搜索栏。对于正常的搜索栏功能,还要确保实现 searchBarSearchButtonClicked(:) 添加 searchBar.resignFirstResponder() 以在单击搜索按钮(或通过按返回键启动)时移除键盘
    • 更新了 Swift 3 的代码:lazy var searchBar = UISearchBar(frame: CGRect.zero)
    【解决方案5】:

    2019 年,你应该使用 UISearchController。

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self.viewModel
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search artists"
        self.navigationItem.searchController = searchController
        self.definesPresentationContext = true
    }
    

    有些类应该符合 UISearchResultsUpdating。我通常将此作为扩展添加到我的 ViewModel。

    extension ArtistSearchViewModel: UISearchResultsUpdating {
    
    func updateSearchResults(for searchController: UISearchController) {
        print("Searching with: " + (searchController.searchBar.text ?? ""))
        let searchText = (searchController.searchBar.text ?? "")
        self.currentSearchText = searchText
        search()
        }
    }
    

    这将产生如下内容:

    【讨论】:

    • 这个解决方案工作正常,但是当我的 tableView 只有几行并且高度显然不够时,我遇到了问题。当我向下滚动时,搜索栏会消失,然后我无法通过再次向上滚动来恢复它,因为它不需要滚动来显示所有行。任何想法如何解决这个问题?
    • @JDK 遗憾的是,我不确定。 :(您可以尝试观察Pull to Refresh,当它被触发时,您可以尝试手动告诉UISearchBar显示。我只是提出一个想法。
    • @JDK92 我知道这是一个迟到的答案,但如果你希望搜索栏始终保持粘性,你可以使用这个 navigationItem.hidesSearchBarWhenScrolling = false
    【解决方案6】:

    适用于 iOS 11 及更高版本

    navigationItem.searchController = searchController
    

    适用于 iOS 10 及更低版本

    navigationItem.titleView = searchController.searchBar;
    

    或者您可以按照this answer 中的说明将其分配为 leftBarButtonItem

    【讨论】:

      【解决方案7】:

      适用于 Swift 5 或字母

      另外,您可以使用此代码。 完全以编程方式

      import UIKit
      
      class SearchTableViewController: UITableViewController {
      
      private lazy var searchController: UISearchController = {
          let sc = UISearchController(searchResultsController: nil)
          sc.searchResultsUpdater = self
          sc.delegate = self
          sc.obscuresBackgroundDuringPresentation = false
          sc.searchBar.placeholder = "Enter A Compiny Name Or Symbole"
          sc.searchBar.autocapitalizationType = .allCharacters
          return sc
      }()
      
      override func viewDidLoad() {
          super.viewDidLoad()
          setupNavigationBar()
      }
      
         private func setupNavigationBar() {
             navigationItem.searchController = searchController
         }
      
       }
      
      // MARK: - UISearchResult Updating and UISearchControllerDelegate  Extension
        extension SearchTableViewController: UISearchResultsUpdating, UISearchControllerDelegate {
          func updateSearchResults(for searchController: UISearchController) {
          
          }
       }
      

      【讨论】:

        【解决方案8】:
            let searchBar = UISearchBar()
            searchBar.sizeToFit()
            searchBar.placeholder = ""
            self.navigationController?.navigationBar.topItem?.titleView = searchBar
        

        【讨论】:

          【解决方案9】:
          func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
          
              searchBar.endEditing(true)
              searchBar.text = nil
              print("## search btn clicked : \(searchBar.text ?? "")")
          } 
          

          【讨论】:

          • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。一个正确的解释would greatly improve 它的长期价值通过展示为什么这是一个很好的解决问题的方法,并将使它对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。
          【解决方案10】:

          适用于 Swift 4 和 5。

          let searchBar = UISearchBar()
          self.navigationItem.titleView = searchBar
          
          let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: nil)
          
          cancelButton.tintColor = #colorLiteral
          
          searchBar.tintColor = #colorLiteral
          
          self.navigationItem.rightBarButtonItem = cancelButton
          

          【讨论】:

            【解决方案11】:

            将 SearchBar 设置为 titleView,将 navigationBar 的高度更改为 56。要解决此问题,您可以将 searchBar 嵌入视图并将其设置为 titleView。

                var offset: CGFloat = 20
            
                // If VC is pushed, back button should be visible
                if navigationController?.navigationBar.backItem != nil {
                    offset = 40
                }
            
                let customFrame = CGRect(x: 0, y: 0, width: view.frame.size.width - offset, height: 44.0)
                let searchBarContainer = UIView(frame: customFrame)
                searchBar = UISearchBar(frame: customFrame)
                searchBarContainer.addSubview(searchBar)
                navigationItem.titleView = searchBarContainer
            

            【讨论】: