我有一个根视图控制器,它在顶部组成一个搜索栏,在底部组成一个子表视图控制器。由于以下原因,我使用了合成而不是将搜索栏分配给表视图的标题:
由于搜索栏位于根视图控制器中,因此我也会在根视图控制器中实例化我的搜索显示控制器。我寻求建议的搜索UI有两个问题:
1)空闲
2)进入搜索栏
3)开始打字
#import "ContactsRootViewController.h"
#import "ContactsViewController.h"
#import "UIView+position.h"
#import "User.h"
#import "UserCellView.h"
#import "UserViewController.h"
@interface ContactsRootViewController ()
@property(nonatomic, strong) UISearchBar* searchBar;
@property(nonatomic, strong) ContactsViewController* contactsViewController;
@property(nonatomic, strong) UISearchDisplayController* searchController;
@property(nonatomic, strong) NSMutableArray* matchedUsers;
@end
@implementation ContactsRootViewController
#pragma mark UIViewController
- (NSString*)title
{
return @"Contacts";
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.matchedUsers = [NSMutableArray array];
self.searchBar = [[UISearchBar alloc] init];
self.searchBar.placeholder = @"Search";
[self.searchBar sizeToFit];
[self.view addSubview:self.searchBar];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.contactsViewController == nil) {
self.contactsViewController = [[ContactsViewController alloc] init];
[self addChildViewController:self.contactsViewController];
self.contactsViewController.view.frame = CGRectMake(
0.0,
self.searchBar.bottomY,
self.view.frame.size.width,
self.view.frame.size.height - self.searchBar.bottomY
);
self.contactsViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
[self.view addSubview:self.contactsViewController.view];
[self.contactsViewController didMoveToParentViewController:self];
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self.contactsViewController];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.matchedUsers.count;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* identifier = @"contactsRootViewUserCell";
UserCellView* cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UserCellView alloc] initWithIdentifier:identifier];
}
cell.user = [self.matchedUsers objectAtIndex:indexPath.row];
return cell;
}
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.navigationController pushViewController:[[UserViewController alloc] initWithUser:[self.matchedUsers objectAtIndex:indexPath.row]] animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [UserCellView height];
}
#pragma mark UISearchDisplayControllerDelegate
- (BOOL)searchDisplayController:(UISearchDisplayController*)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self.matchedUsers removeAllObjects];
searchString = [searchString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (searchString.length > 0) {
for (User* user in self.contactsViewController.allUsers) {
NSRange match = [user.userDisplayName rangeOfString:searchString options:NSCaseInsensitiveSearch];
if (match.location != NSNotFound) {
[self.matchedUsers addObject:user];
}
}
}
return YES;
}
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
[self.searchBar resignFirstResponder];
}
@end
答案 0 :(得分:1)
我重新实现了UISearchDisplayController,调用了我的实现SearchController。它执行相同的操作并具有类似的委托回调,但搜索结果的框架可以由程序员控制。
#import <Foundation/Foundation.h>
@class SearchController;
@protocol SearchControllerDelegate <NSObject>
@required
- (BOOL)searchController:(SearchController*)controller shouldReloadTableForSearchString:(NSString*)searchText;
@optional
- (void)searchController:(SearchController*)controller didShowSearchResultsTableView:(UITableView*)tableView;
- (void)searchController:(SearchController *)controller didHideSearchResultsTableView:(UITableView *)tableView;
- (void)searchControllerDidBeginSearch:(SearchController*)controller;
- (void)searchControllerDidEndSearch:(SearchController*)controller;
@end
@interface SearchController : UIViewController <UISearchBarDelegate>
@property(nonatomic, weak) NSObject<SearchControllerDelegate>* delegate;
@property(nonatomic, weak) NSObject<UITableViewDataSource>* searchResultsDataSource;
@property(nonatomic, weak) NSObject<UITableViewDelegate>* searchResultsDelegate;
@property(nonatomic, strong, readonly) UITableView* searchResultsTableView;
- (id)initWithSearchBar:(UISearchBar*)searchBar;
@end
#import "SearchController.h"
#import "UIView+position.h"
@interface SearchController ()
@property(nonatomic, strong) UISearchBar* searchBar;
@property(nonatomic, strong) UIButton* searchResultsVeil;
@property(nonatomic, strong, readwrite) UITableView* searchResultsTableView;
@property(nonatomic, assign) BOOL searchResultsTableViewHidden;
- (void)didTapSearchResultsVeil;
- (void)hideSearchResults;
@end
@implementation SearchController
#pragma mark UIViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.searchResultsTableView deselectRowAtIndexPath:[self.searchResultsTableView indexPathForSelectedRow] animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.userInteractionEnabled = NO;
}
#pragma mark SearchController ()
- (void)hideSearchResults
{
self.searchBar.text = nil;
[self.searchResultsTableView reloadData];
self.searchResultsTableViewHidden = YES;
[self.searchBar resignFirstResponder];
}
- (void)didTapSearchResultsVeil
{
[self hideSearchResults];
}
- (void)setSearchResultsTableViewHidden:(BOOL)searchResultsTableViewHidden
{
if (self.searchResultsTableView != nil) {
if (self.searchResultsTableView.hidden && !searchResultsTableViewHidden) {
self.searchResultsTableView.hidden = searchResultsTableViewHidden;
if ([self.delegate respondsToSelector:@selector(searchController:didShowSearchResultsTableView:)]) {
[self.delegate searchController:self didShowSearchResultsTableView:self.searchResultsTableView];
}
} else if (!self.searchResultsTableView.hidden && searchResultsTableViewHidden) {
self.searchResultsTableView.hidden = searchResultsTableViewHidden;
if ([self.delegate respondsToSelector:@selector(searchController:didHideSearchResultsTableView:)]) {
[self.delegate searchController:self didHideSearchResultsTableView:self.searchResultsTableView];
}
}
}
}
- (BOOL)searchResultsTableViewHidden
{
return self.searchResultsTableView == nil || self.searchResultsTableView.hidden;
}
#pragma mark SearchController
- (id)initWithSearchBar:(UISearchBar *)searchBar
{
if (self = [super init]) {
self.searchBar = searchBar;
self.searchBar.delegate = self;
}
return self;
}
- (void)setSearchResultsDataSource:(NSObject<UITableViewDataSource> *)searchResultsDataSource
{
_searchResultsDataSource = searchResultsDataSource;
if (self.searchResultsTableView != nil) {
self.searchResultsTableView.dataSource = searchResultsDataSource;
}
}
- (void)setSearchResultsDelegate:(NSObject<UITableViewDelegate> *)searchResultsDelegate
{
_searchResultsDelegate = searchResultsDelegate;
if (self.searchResultsTableView != nil) {
self.searchResultsTableView.delegate = searchResultsDelegate;
}
}
#pragma mark UISearchBarDelegate
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ([self.delegate searchController:self shouldReloadTableForSearchString:searchText]) {
[self.searchResultsTableView reloadData];
self.searchResultsTableViewHidden = [self.searchResultsTableView.dataSource tableView:self.searchResultsTableView numberOfRowsInSection:0] == 0;
}
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[searchBar setShowsCancelButton:YES animated:YES];
if (self.searchResultsVeil == nil) {
self.searchResultsVeil = [[UIButton alloc] initWithFrame:self.view.bounds];
self.searchResultsVeil.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.6];
self.searchResultsVeil.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.searchResultsVeil addTarget:self action:@selector(didTapSearchResultsVeil) forControlEvents:UIControlEventTouchUpInside];
self.searchResultsTableView = [[UITableView alloc] initWithFrame:self.searchResultsVeil.bounds style:UITableViewStylePlain];
self.searchResultsTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
if ([self.searchResultsTableView respondsToSelector:@selector(setSeparatorInset:)]) {
self.searchResultsTableView.separatorInset = UIEdgeInsetsMake(
0.0,
self.searchResultsTableView.width,
0.0,
0.0
);
}
self.searchResultsTableViewHidden = YES;
if (self.searchResultsDataSource != nil) {
self.searchResultsTableView.dataSource = self.searchResultsDataSource;
}
if (self.searchResultsDelegate != nil) {
self.searchResultsTableView.delegate = self.searchResultsDelegate;
}
[self.view addSubview:self.searchResultsVeil];
[self.searchResultsVeil addSubview:self.searchResultsTableView];
}
self.view.userInteractionEnabled = YES;
self.searchResultsVeil.hidden = NO;
if ([self.delegate respondsToSelector:@selector(searchControllerDidBeginSearch:)]) {
[self.delegate searchControllerDidBeginSearch:self];
}
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
[searchBar setShowsCancelButton:NO animated:YES];
self.view.userInteractionEnabled = NO;
self.searchResultsVeil.hidden = YES;
if ([self.delegate respondsToSelector:@selector(searchControllerDidEndSearch:)]) {
[self.delegate searchControllerDidEndSearch:self];
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[self hideSearchResults];
}
@end
self.searchController = [[SearchController alloc] initWithSearchBar:self.searchBar];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self addChildViewController:self.searchController];
self.searchController.view.frame = CGRectMake(
self.searchBar.x,
self.searchBar.bottomY,
self.searchBar.width,
self.view.height - self.searchBar.bottomY
);
[self.view addSubview:self.searchController.view];
[self.searchController didMoveToParentViewController:self];
答案 1 :(得分:0)
看起来您的视图控制器没有定义演示文稿上下文。我有类似的问题,并能够通过设置
来解决它self.definesPresentationContext = YES;
viewDidLoad
中的。根据文档,这个属性是
一个布尔值,指示当视图控制器或其后代之一呈现视图控制器时是否覆盖此视图控制器的视图。