25

我有一个tableview用于在我的应用程序中显示设备列表的工具。当 viewWillAppear 被调用时,我添加了self.searchDisplayController.searchBar as a subview to a headerView. 然后我分配self.tableView.tableHeaderView = headerView. 它看起来像这样: 在此处输入图像描述

我向下滚动 tableview 以便 headerview 消失,然后通过点击单元格转到其他视图控制器。当我回到这个 tableView 时,向上滚动到 headerView,searchBar 变得不可见,但是在点击不可见区域时,searchDisplayController 被激活并且取消按钮不起作用。这仅适用于 iOS 7。为什么会这样? 在此处输入图像描述
注意:只有当我回到 tableViewController 时 headerView 不在视图中时才会发生这种情况。

4

9 回答 9

18

我刚遇到同样的问题。当我在结束搜索状态下调试到 UISearchDisplayController 的委托方法时,searchBar 成为 UIView 的子视图,而不是 UITableView。请看下面的代码:

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
    //My Solution: remove the searchBar away from current super view,
    //then add it as subview again to the tableView
    UISearchBar *searchBar = controller.searchBar;
    UIView *superView = searchBar.superview;
    if (![superView isKindOfClass:[UITableView class]]) {
        NSLog(@"Error here");
        [searchBar removeFromSuperview];
        [self.tableView addSubview:searchBar];
    }
    NSLog(@"%@", NSStringFromClass([superView class]));
}

我的解决方案是将 searchBar 从当前超级视图中删除,然后将其作为子视图再次添加到 tableView。我已经测试成功了。希望有帮助!

问候

于 2014-01-03T17:06:40.293 回答
5

我有完全一样的问题。搜索栏仍然存在并且可以接收触摸事件。但是它没有被渲染。我相信问题出在 UISearchDisplaycontroller 中,因为如果我不使用 UISearchDisplayController,它会呈现得很好。我最终编写了一个自定义 SearchDisplaycontroller 来替换它。这是非常基本的,只做我需要的。

使用它的方式与普通 UISearchDisplayController 相同,但 self.searchDisplayController 不会返回任何内容。您将不得不使用另一个指针来引用自定义搜索显示控制器。

看起来像一个丑陋的工作,但唯一对我有用的工作。渴望听到替代品。

@protocol SearchDisplayDelegate;

@interface SearchDisplayController : NSObject<UISearchBarDelegate>

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController;

@property(nonatomic,assign)                           id<SearchDisplayDelegate> delegate;

@property(nonatomic,getter=isActive)  BOOL            active;  // configure the view controller for searching. default is NO. animated is NO
- (void)setActive:(BOOL)visible animated:(BOOL)animated;       // animate the view controller for searching

@property(nonatomic,readonly)                         UISearchBar                *searchBar;
@property(nonatomic,readonly)                         UIViewController           *searchContentsController; // the view we are searching (often a UITableViewController)
@property(nonatomic,readonly)                         UITableView                *searchResultsTableView;   // will return non-nil. create if requested
@property(nonatomic,assign)                           id<UITableViewDataSource>   searchResultsDataSource;  // default is nil. delegate can provide
@property(nonatomic,assign)                           id<UITableViewDelegate>     searchResultsDelegate;

@end


@protocol SearchDisplayDelegate <NSObject>
// implement the protocols you need
@optional
@end

实施

@implementation SearchDisplayController {
    UISearchBar *_searchBar;
    UIViewController *_viewController;
    UITableView *_searchResultsTableView;
    UIView *_overLay;
}

- (void)dealloc {
    [_searchBar release];
    [_searchResultsTableView release];
    [_overLay release];
    [super dealloc];
}

- (UIViewController *)searchContentsController {
    return _viewController;
}

- (UITableView *)searchResultsTableView {
    return _searchResultsTableView;
}

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController {
    self = [super init];
    if (self) {
        _searchBar = [searchBar retain];
        _searchBar.delegate = self;
        _viewController = viewController;
        _searchResultsTableView = [[UITableView alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(_searchBar.frame), _viewController.view.frame.size.width, _viewController.view.frame.size.height - CGRectGetMaxY(_searchBar.frame))];
        _overLay = [[UIView alloc]initWithFrame:_searchResultsTableView.frame];
        _overLay.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(overLayTapped)];
        [_overLay addGestureRecognizer:tap];
        [tap release];
    }
    return self;
}
- (void)setSearchResultsDataSource:(id<UITableViewDataSource>)searchResultsDataSource {
    _searchResultsTableView.dataSource = searchResultsDataSource;
}

- (void)setSearchResultsDelegate:(id<UITableViewDelegate>)searchResultsDelegate {
    _searchResultsTableView.delegate = searchResultsDelegate;
}

- (void)overLayTapped {
    [self setActive:NO animated:YES];
    [_searchBar resignFirstResponder];
    _searchBar.text = nil;
    _searchBar.showsCancelButton = NO;
}

- (void)setActive:(BOOL)visible animated:(BOOL)animated {
    UIView *viewToAdd = nil;
    if (!_searchBar.text.length) {
        viewToAdd = _overLay;
    } else {
        viewToAdd = _searchResultsTableView;
    }
    float a = 0;
    if (visible) {
        [_viewController.view addSubview:viewToAdd];
        a = 1.0;
    }
    if ([_viewController.view respondsToSelector:@selectore(scrollEnabled)]) {
        ((UIScrollView *)_viewController.view).scrollEnabled = !visible;
    }

    if (animated) {
        [UIView animateWithDuration:0.2 animations:^{
            _overLay.alpha = a;
            _searchResultsTableView.alpha = a;
        }];
    } else {
        _overLay.alpha = a;
        _searchResultsTableView.alpha = a;
    }
}

- (void)setActive:(BOOL)active {
    [self setActive:active animated:YES];
}

#pragma mark - UISearchBar delegate protocols

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    [self setActive:YES animated:YES];
    searchBar.showsCancelButton = YES;
    [_searchResultsTableView reloadData];
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {

}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [_searchResultsTableView reloadData];
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self overLayTapped];
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (searchText.length) {
        [_overLay removeFromSuperview];
        [_viewController.view addSubview:_searchResultsTableView];
    } else {
        [_searchResultsTableView removeFromSuperview];
        [_viewController.view addSubview:_overLay];
    }
        [_searchResultsTableView reloadData];
}

@end

更新:关于如何以编程方式使用它

声明一个 ivar

SearchDisplayController *mySearchDisplayController;

以编程方式初始化它

mySearchDisplayController = [[SearchDisplayController alloc]initWithSearchBar:mySearchBar contentsController:self];

将搜索栏添加到您的表格视图

self.tableView.headerView = mySearchBar;

使用 mySearchDisplayController 作为对 custon 类的引用,而不是在 self.searchDisplayController 上。

于 2013-09-30T04:35:24.440 回答
2


在我的例子中,在其标题视图中包含搜索显示控制器的搜索栏的表格视图几乎在视图出现时就被重新加载。正是在这一点上,搜索栏将停止呈现。当我滚动表格时,它会重新出现。还值得一提的是,我的表包含一个 UIRefreshControl 而不是UITableViewController 子类。

我的修复涉及在加载表(并结束刷新控件刷新)之前非常快速地将搜索显示控制器设置为活动和非活动:

[self.tableView reloadData];    
[self.refreshControl endRefreshing];
[self.searchDisplayController setActive:YES animated:NO];
[self.searchDisplayController setActive:NO];


有点hack,但它对我有用。

于 2013-11-06T16:47:15.647 回答
2

我赞同Phien Tram 的回答。请点赞。我自己积分不够。

我有一个类似的问题,当我反复点击它时,从情节提要加载的搜索栏会消失,调用和关闭搜索。他的解决方案解决了这个问题。

似乎有一个错误,搜索显示控制器的重复调用和解除并不总是将搜索栏返回到表格视图。

我会说我对解决方案对现有视图层次结构的依赖感到不舒服。Apple 似乎会在每个主要版本中重新调整它。此代码可能会在 iOS 8 中中断。

我认为永久的解决方案需要 Apple 进行修复。

于 2014-01-04T18:29:28.120 回答
2

使用调试器,我发现 UISearchBar 最初是 tableHeaderView 的子视图 - 但当它消失时,它已成为 tableView 本身的子视图。这可能是由 UISearchDisplayController 以某种方式完成的......所以我做了以下 hack 来简单地将 UISearchBar 返回到标题视图:

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  if(!self.searchDisplayController.isActive && self.searchBar.superview != self.tableView.tableHeaderView) {
    [self.tableView.tableHeaderView addSubview:self.searchBar];
  }
}

似乎在 iOS 7 和 6 上都可以正常工作 :)

(需要检查 searchDisplayController 是否处于活动状态,否则搜索栏会在搜索过程中消失)

于 2013-11-14T16:35:55.323 回答
1

我有同样的问题,我可以在创建 UISearchDisplayController 后调用下一行来修复它

[self performSelector:@selector(setSearchDisplayController:) withObject:displayController];

我的 viewDidLoad 函数如下所示:

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 44)];
searchBar.placeholder = NSLocalizedString(@"Search", @"Search");

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

[self performSelector:@selector(setSearchDisplayController:) withObject:displayController];

self.tableView.contentOffset = CGPointMake(0, 44);
self.tableView.tableHeaderView = searchBar;

感谢这个答案:https ://stackoverflow.com/a/17324921/1070393

于 2013-11-20T12:38:10.800 回答
1

我遇到过类似的问题,经过一番挖掘,我发现这是 UISearchBar 层次结构中的一个错误。这个 hacky 解决方案在 iOS 7 中对我有用,但请注意,这可能会在未来的 iOS 版本中中断:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    UIView *buggyView = [self.searchDisplayController.searchBar.subviews firstObject];
    // buggyView bounds and center are incorrect after returning from controller, so adjust them.
    buggyView.bounds = self.searchDisplayController.searchBar.bounds;
    buggyView.center = CGPointMake(CGRectGetWidth(buggyView.bounds)/2, CGRectGetHeight(buggyView.bounds)/2);
}
于 2014-07-01T06:47:04.940 回答
1

使用 UITableView 上方的 UISearchBar,然后制作 IBOutlet 并将它们与文件所有者连接到 UISearchbar

示例 - .h 文件

#import <UIKit/UIKit.h>

@interface LocationViewController : UIViewController<UISearchBarDelegate>
{

   BOOL IsSearchOn;

}

@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;

@property (strong, nonatomic) IBOutlet UITableView *TBVLocation;

.m 文件

#pragma mark -


#pragma mark UISearchBar Delegate Methods



-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

{

    [self.searchResult removeAllObjects];

     if(searchText.length == 0)
      {
           IsSearchOn=NO;
        // [filteredTableData removeAllObjects];
           [self.searchBar resignFirstResponder];
        // [self .tblView reloadData];


     }
   else
     {
       IsSearchOn=YES;

       if(searchText != nil && ![searchText isEqualToString:@""])
       {

        /*            NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@", searchText];

        self.searchResult = [NSMutableArray arrayWithArray: [searchArray filteredArrayUsingPredicate:resultPredicate]];*/
        for(int i=0;i<[[arrCountryList valueForKey:@"country_name"] count];i++)
        {


            NSRange titleRange =    [[[[arrCountryList valueForKey:@"country_name"] objectAtIndex:i] lowercaseString] rangeOfString:[searchText lowercaseString]];

            if(titleRange.location != NSNotFound)
                [self.searchResult addObject:[arrCountryList objectAtIndex:i]];

        }

        [TBVLocation reloadData];
    }
   }

 }



- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar

 {


 [searchBar resignFirstResponder];


 }


-(void)searchBarCancelButtonClicked:(UISearchBar *) searchBar


{


  [searchBar resignFirstResponder];

  IsSearchOn=NO;

  searchBar.text = nil;

  [TBVLocation reloadData];



}

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar

{

  [searchBar resignFirstResponder];
  return YES;
}

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
   searchBar.showsCancelButton = YES;
   searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
   // IsSearchOn=YES;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar

{
    IsSearchOn=NO;
    searchBar.showsCancelButton = NO;
   [TBVLocation reloadData];
   [searchBar resignFirstResponder];
}

它会像魅力一样起作用。

于 2014-07-02T07:59:26.787 回答
0

我遇到了同样的问题并测试了这个线程中提出的一些解决方案,但它们并没有为我解决问题。之前,我在

 - (void)viewDidLoad

我的 ViewController 在代码中的方法。

UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:searchBarView.frame];
searchBar.delegate = self;
searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
ect...

为我解决这个问题的是我在 InterfaceBuilder 中添加了一个 UISearchbar,在我的 ViewController 中创建了一个插座,并将这个 UISearchBar 添加到我的 UISearchDisplayController。

self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar(<--outlet) contentsController:self];

希望这也可以帮助一些人

于 2014-06-16T08:24:02.923 回答