2013-09-27 26 views
24

我有一个tableview用于显示我的应用程序中的设备列表。当viewWillAppear被调用时,我添加self.searchDisplayController.searchBar as a subview to a headerView。然后我分配self.tableView.tableHeaderView = headerView。它看起来像这样: enter image description hereSearchBar从iOS 7的headerview中消失

我向下滚动tableview,使headerview离开视图,然后通过点击单元格转到其他视图控制器。当我回到这个tableView时,向上滚动到headerView,searchBar变得不可见,但是在点击不可见区域时,searchDisplayController被激活,取消按钮不起作用。这仅适用于iOS 7。这是为什么发生? enter image description here
注意:只有当我回到tableViewController时,headerView不在视图中。

+0

在某处添加断点并查看headerView是否仍然存在。 –

+0

@LordZsolt headerView作为我在searchBar左侧添加的按钮存在,并且可见且正在工作。 –

+0

因此,带有两个箭头和线条的按钮显示出来,但不是搜索文本框? –

回答

5

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

使用它与正常的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 

更新:关于如何使用这个progammatically

声明伊娃

SearchDisplayController *mySearchDisplayController; 

初始化程序

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

添加搜索栏到您的tableview

self.tableView.headerView = mySearchBar; 

使用mySearchDisplayController作为参考custon类,而不是在self.searchDisplayController。

+0

其实我也在使用searchBar和searchDisplaycontroller委托功能。我将searchDisplayController分配给上述视图控制器的xib中的这个类。 –

+0

所以我的解决方案不适合你? – tzl

+0

不......不适合我。 –

2


在我的情况下,几乎在视图出现后,几乎立即重新加载在其标题视图中保存搜索显示控制器搜索栏的表视图。在这一点上,搜索栏将停止呈现。当我滚动桌子时,它会重新出现。还值得一提的是,我的表中包含UIRefreshControl,并且是而不是的UITableViewController子类。

我定期参与加载表(和结束刷新控制刷新)后,之前设置搜索显示控制器激活,然后不活动非常迅速:

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


一个黑客一点,但它的工作原理为了我。

1

使用调试器,我发现的UISearchBar最初是tableHeaderView的子视图 - 但是当它消失,它已成为的tableView本身的孩子。这可能已通过某种方式UISearchDisplayController做...所以我做了下面的技巧简单的的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不活跃是必要的,否则搜索过程中的沙棘栏消失)

1

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

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

我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

18

我刚刚有同样的问题。当我去调试到末搜索状态UISearchDisplayController的委托方法,搜索栏成为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])); 
} 

我的解决方法是删除搜索栏从当前的超图了,然后重新添加为子视图中的tableView。我已经测试成功。 希望有所帮助!

问候

+0

这很好,你发现了问题!但是关于解决方案还有一个警告:当从超级视图中删除searchBar并将其添加到tableview时,输入焦点会丢失! –

+0

Nice.Work for Work。 – tounaobun

2

我赞同Phien Tram's answer。请注意它。我自己没有足够的观点。

我也有类似的问题,即从故事板加载的搜索栏会消失,当我反复挖掘它,调用和辞退搜索。他的解决方案修复了这个问题。

似乎有哪里反复搜索显示控制器的调用和辞退并不总是给搜索栏回表视图中的错误。

,我会说我对这个解决方案对现有的视图层次结构的依赖不舒服。苹果公司似乎在每个主要版本都重新洗牌。此代码可能会与iOS 8打破。

我认为永久性解决方案需要Apple修复。

+0

取消按钮无法正常工作,似乎已从7.1 beta 2中修复,但我仍然遇到与搜索栏消失相似的问题。 – aednichols

0

我有同样的问题,并测试了一些在这个线程这里提出的解决方案,但他们并没有解决这个问题对我来说。 以前,我加入并在我的代码的ViewController的

- (void)viewDidLoad 

方法配置的的UISearchBar。

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]; 

希望这也可以帮助一些人

1

我遇到类似的问题,一些挖后,我发现这是层次的UISearchBar的错误。这哈克解决方案的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); 
} 
+0

This Works!谢谢 –

1

使用的UISearchBar以上的UITableView,然后让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]; 
} 

它会像魅力一样工作。