据我了解,UISearchController
的默认行为是:
SearchResultsController
。SearchResultsController
。我想显示SearchResultsController
,即使搜索栏为空但被选中(即上面的情况1)。
简单地说,我想显示搜索结果,而不是背景调光。
有没有办法做到这一点?
更多澄清:
我没有使用UISearchController
来过滤显示它的视图上显示的结果,而是使用其他一些不相关的结果。
这就像facebook在其“新闻Feed”中所做的那样。点击搜索栏最初会显示搜索建议,然后在我们开始编辑时显示可能与新闻Feed无关的搜索结果。
答案 0 :(得分:32)
您只需实施UISearchResultsUpdating
协议并将结果控制器视图设置为始终显示在updateSearchResultsForSearchController
中:
func updateSearchResultsForSearchController(searchController: UISearchController) {
// Always show the search result controller
searchController.searchResultsController?.view.hidden = false
// Update your search results data and reload data
..
}
这是有效的,因为即使激活搜索栏而没有任何文本,也会调用该方法。
答案 1 :(得分:31)
如果您的searchBar处于活动状态但没有文本,则会显示基础tableView结果。这是内置行为,以及为该状态隐藏searchResultsController的原因。
要在搜索处于活动状态但不进行过滤时更改行为,您必须在通常仍处于隐藏状态时显示searchResultsController。
通过<UISearchResultsUpdating>
和updateSearchResultsForSearchController:
可能有一种很好的方法可以实现这一目标。如果您可以通过协议解决,那么这是首选方式。
如果这没有帮助,你就会被黑客攻击内置行为。我不会推荐或依赖它,而且它会很脆弱,但如果你选择这个选项,这是一个答案:
确保tableViewController符合<UISearchControllerDelegate>
,并添加
self.searchController.delegate = self;
实施willPresentSearchController:
- (void)willPresentSearchController:(UISearchController *)searchController
{
dispatch_async(dispatch_get_main_queue(), ^{
searchController.searchResultsController.view.hidden = NO;
});
}
这使得searchResultsController
在其UISearchController
设置为隐藏后可见。
实施didPresentSearchController:
- (void)didPresentSearchController:(UISearchController *)searchController
{
searchController.searchResultsController.view.hidden = NO;
}
要想更好地解决内置行为,请参阅malhal's answer。
答案 2 :(得分:13)
我尝试过PetahChristian解决方案,当我们第一次关注搜索栏时,预加载结果显示出来,但是当我们输入内容然后清除它时,预加载结果将不再出现。
我提出了另一个解决方案。我们只需要在SearchResultsController中添加一个委托,并在我们的searchController.searchBar.text为空时调用它。像这样:
SearchResultsController:
protocol SearchResultsViewControllerDelegate {
func reassureShowingList() -> Void
}
class FullSearchResultsViewController: UIViewController, UISearchResultsUpdating{
var delegate: SearchResultsViewControllerDelegate?
...
func updateSearchResultsForSearchController(searchController: UISearchController) {
let query = searchController.searchBar.text?.trim()
if query == nil || query!.isEmpty {
...
self.delegate?.reassureShowingList()
...
}
...
}
在控制器中包含SearchController,我们添加了委托:
self.searchResultsController.delegate = self
func reassureShowingList() {
searchController.searchResultsController!.view.hidden = false
}
答案 3 :(得分:11)
对于像这样棘手的事情,我推荐大锤方法!那是为了检测何时某些东西试图将其隐藏起来以及何时隐藏它,将其更改回来。这可以通过KVO(键值观察)来完成。无论如何都可以使用,无需处理搜索栏的所有复杂性。对不起,代码很复杂,但KVO是一种较旧的API,但我的代码遵循推荐的做法。在你的SearchResultsViewController中输入:
static int kHidden;
@implementation SearchResultsViewController
-(void)viewDidLoad{
[super viewDidLoad];
[self.view addObserver:self
forKeyPath:@"hidden"
options:(NSKeyValueObservingOptionNew |
NSKeyValueObservingOptionOld)
context:&kHidden];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
// if it was our observation
if(context == &kHidden){
// if the view is hidden then make it visible.
if([[change objectForKey:NSKeyValueChangeNewKey] boolValue]){
self.view.hidden = NO;
}
}
else{
// if necessary, pass the method up the subclass hierarchy.
if([super respondsToSelector:@selector(observeValueForKeyPath:ofObject:change:context:)]){
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}
}
- (void)dealloc
{
[self.view removeObserver:self forKeyPath:@"hidden"];
}
// Here have the rest of your code for the search results table.
@end
这适用于所有情况,包括文本是否已清除。
最后,为了防止表格在搜索激活时将淡化淡化变为灰色然后变为白色,请使用:
self.searchController.dimsBackgroundDuringPresentation = NO;
答案 4 :(得分:6)
Swift 3版本:
如果您的searchResultController
不是nil并且您使用单独的表视图控制器来显示搜索结果,那么您可以使该表视图控制器符合UISearchResultUpdating
和updateSearchResults
功能,你可以简单地取消隐藏视图。
func updateSearchResults(for searchController: UISearchController) {
view.hidden = false
}
Swift 4版本:
func updateSearchResults(for searchController: UISearchController) {
view.isHidden = false
}
答案 5 :(得分:3)
@ malhal方法的Swift 2.3版本:
class SearchResultsViewController : UIViewController {
var context = 0
override func viewDidLoad() {
super.viewDidLoad()
// Add observer
view.addObserver(self, forKeyPath: "hidden", options: [ .New, .Old ], context: &context)
}
deinit {
view.removeObserver(self, forKeyPath: "hidden")
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if context == &self.context {
if change?[NSKeyValueChangeNewKey] as? Bool == true {
view.hidden = false
}
} else {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
}
}
}
答案 6 :(得分:3)
我最近在UISearchController
工作。我想在搜索栏为空时在searchResultsController
中显示搜索记录。因此,只要searchResultsController
出现,UISearchController
就会显示出来。
在这里,我使用另一种解决方案,通过覆盖自定义视图中的searchResultsController
属性,使hidden
始终可见。
例如,我的searchResultsController
是UITableViewController
。我创建了一个 VisibleTableView 作为UITableView
的子类,然后在xib中将UITableView
自定义类searchResultsController
更改为 VisibleTableView 或故事板。这样,我的searchResultsController
永远不会被UISearchController
隐藏。
这里有好处:
比KVO更容易实施。
显示searchResultsController
没有延迟。在&#34; updateSearchResults&#34;中翻转隐藏的标记。委托方法有效,但有延迟显示searchResultsController
。
它不会重置隐藏的标志,因此在隐藏和可见之间没有UI间隙/跳跃。
Swift 3示例代码:
class VisibleTableView: UITableView {
override var isHidden: Bool {
get {
return false
}
set {
// ignoring any settings
}
}
}
答案 7 :(得分:3)
隐藏的是搜索结果控制器的视图。因此,只要隐藏它就足以取消隐藏它。只需在搜索结果控制器中执行以下操作:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.view.isHidden = false
}
func updateSearchResults(for searchController: UISearchController) {
self.view.isHidden = false
// ... your other code goes here ...
}
现在结果视图(即表格视图)始终可见,即使搜索栏文本为空。
顺便说一句,iOS Mail应用程序的行为与此类似,我认为它是如何实现的(除非Apple可以访问某些秘密的私有UISearchController设置)。
[在iOS 10和iOS 11中测试;我没有在任何早期的系统上进行测试。]
答案 8 :(得分:0)
我认为你错了。
SearchResultsController仅在有结果时出现。这与你的解释略有不同。
根据搜索栏中的文本手动加载结果。因此,如果搜索栏为空,您可以拦截它并返回您自己的一组结果。
答案 9 :(得分:0)
如果您不想将结果调暗,请将dimsBackgroundDuringPresentation
属性设置为false
。
这将确保在搜索过程中基础内容不会变暗。
即使searchText为空,您还必须确保返回结果,否则将显示空的tableview。
答案 10 :(得分:0)
我花了很多时间用这个,最终我使用的解决方案就像@ malhals一样,但使用facebook的KVOController https://github.com/facebook/KVOController可以大大减少代码量。这里的另一个优点是,如果您的searchResultsController是UINavigationController
,那么您不需要将其子类化以添加@malhal的代码。
// always show searchResultsController, even if text is empty
[self.KVOController observe:self.searchController.searchResultsController.view keyPath:@"hidden" options:NSKeyValueObservingOptionNew block:^(id observer, UIView* view, NSDictionary *change) {
if ([change[NSKeyValueChangeNewKey] boolValue] == YES) {
view.hidden = NO;
}
}];
self.searchController.dimsBackgroundDuringPresentation = NO;
答案 11 :(得分:0)
最简单的方法是将ReactiveCocoa与此扩展名https://github.com/ColinEberhardt/ReactiveTwitterSearch/blob/master/ReactiveTwitterSearch/Util/UIKitExtensions.swift
一起使用 presentViewController(sc, animated: true, completion: {
sc.searchResultsController?.view.rac_hidden.modify({ value -> Bool in
return false
})
} )
其中sc是你的UISearchController
答案 12 :(得分:0)
我非常喜欢Simon Wang的回答并使用它,这就是我所做的,它完美无缺:
我在自定义类中继承了UISearchController:
class CustomClass: UISearchController {
override var searchResultsController: UIViewController? {
get {
let viewController = super.searchResultsController
viewController?.view.isHidden = false
return viewController
}
set {
// nothing
}
}
}
另外请确保您的代码中没有任何内容:
self.resultsSearchController.isActive = true
resultsSearchController是我的UISearchController
答案 13 :(得分:0)
malhals answer的Swift 4 版本:
class SearchController: UISearchController {
private var viewIsHiddenObserver: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
viewIsHiddenObserver = self.searchResultsController?.view.observe(\.hidden, changeHandler: { [weak self] (view, _) in
guard let searchController = self else {return}
if view.isHidden && searchController.searchBar.isFirstResponder {
view.isHidden = false
}
})
}
}
请注意[weak self]
。否则你会引入一个保留周期。