8
votes

I have a UISearchBar added as a subview to a UICollectionView, and attached to a UISearchDisplayController.

I set it up in viewDidLoad:

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

[self.collectionView addSubview:self.searchBar];

When I push another view controller to the navigation controller then pop it, the search bar disappears. This only happens if the collection view is scrolled down enough for the search bar to be hidden. Also, even though the search bar disappears, tapping the white space where it's supposed to be activates the search display controller attached to it.

This happens only on iOS 7, and if I remove the search display controller the search bar will not disappear.

One more thing worth mentioning. When the search bar has disappeared, if I push another view controller then pop it, the bar will be visible again.

Apparently this is a bug of UISearchDisplayController on iOS 7, so any ideas on how to work around it?

1
Did you find a solution ? I am encounter the same problem. Added a UISearchDisplayController.uisearchbar to the collectionView header. If user push to another view and pop back. the uisearchbar will disappear. But it could still active if user tap the empty space.Ken Hui
I couldn't find a workout so I ended up rewriting UISearchDisplayController on my own.Hesham
You mean you animate the active on uisearchbar and add the uitableview on your own ? Actually I just need the "active" animation. Not sure if there is a easy way to generate similar effect.Ken Hui
Yes, I manage the navigation bar/search bar animations and add/remove the UITableView. I will post the code in a separate answer.Hesham

1 Answers

4
votes

I ended up implementing UISearchDisplayController on my own. Here's my code.

ZBNSearchDisplayController.h

@protocol ZBNSearchDisplayDelegate;

@interface ZBNSearchDisplayController : NSObject<UISearchBarDelegate>

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController;
- (void)setActive:(BOOL)visible animated:(BOOL)animated;

@property(nonatomic,assign) id<ZBNSearchDisplayDelegate> delegate;
@property(nonatomic, getter = isActive) BOOL active;
@property(nonatomic, readonly) UISearchBar *searchBar;
@property(nonatomic, readonly) UIViewController *searchContentsController;
@property(nonatomic, readonly) UITableView *searchResultsTableView;
@property(nonatomic, assign) id<UITableViewDataSource> searchResultsDataSource;
@property(nonatomic, assign) id<UITableViewDelegate> searchResultsDelegate;

@end

@protocol ZBNSearchDisplayDelegate <NSObject>

@optional

- (void)searchDisplayControllerWillBeginSearch:(ZBNSearchDisplayController *)controller;
- (void)searchDisplayControllerDidBeginSearch:(ZBNSearchDisplayController *)controller;
- (void)searchDisplayControllerWillEndSearch:(ZBNSearchDisplayController *)controller;
- (void)searchDisplayControllerDidEndSearch:(ZBNSearchDisplayController *)controller;
- (void)textDidChange:(NSString *)searchText;
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope;

@end

ZBNSearchDisplayController.m

#import "ZBNSearchDisplayController.h"

@implementation ZBNSearchDisplayController

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController {
    self = [super init];

    if (self) {
        _searchBar = searchBar;
        _searchBar.delegate = self;
        _searchContentsController = viewController;

        CGFloat y = 64.0f;
        CGFloat height = _searchContentsController.view.frame.size.height - y;

        _searchResultsTableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, y, _searchContentsController.view.frame.size.width, height)];
        _searchResultsTableView.scrollsToTop = NO;
    }

    return self;
}

- (void)setSearchResultsDataSource:(id<UITableViewDataSource>)searchResultsDataSource {
    _searchResultsTableView.dataSource = searchResultsDataSource;
}

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

- (void)setActive:(BOOL)visible animated:(BOOL)animated {
    if (!visible) {
        [_searchBar resignFirstResponder];
        _searchBar.text = nil;
        _searchBar.showsCancelButton = NO;
    }

    if (visible && [self.delegate respondsToSelector:@selector(searchDisplayControllerWillBeginSearch:)]) {
        [self.delegate searchDisplayControllerWillBeginSearch:self];
    } else if (!visible && [self.delegate respondsToSelector:@selector(searchDisplayControllerWillEndSearch:)]) {
        [self.delegate searchDisplayControllerWillEndSearch:self];
    }

    [_searchContentsController.navigationController setNavigationBarHidden:visible animated:YES];

    float alpha = 0;

    if (visible) {
        [_searchContentsController.view addSubview:_searchResultsTableView];
        alpha = 1.0;
    }

    if ([_searchContentsController.view respondsToSelector:@selector(scrollEnabled)]) {
        ((UIScrollView *)_searchContentsController.view).scrollEnabled = !visible;
    }

    if (animated) {
        [UIView animateWithDuration:0.2 animations:^{
            _searchResultsTableView.alpha = alpha;
        } completion:^(BOOL finished) {
            self.active = visible;
        }];
    } else {
        _searchResultsTableView.alpha = alpha;
    }
}

#pragma mark - UISearchBarDelegate

- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope {
    if ([self.delegate respondsToSelector:@selector(searchBar:selectedScopeButtonIndexDidChange:)]) {
        [self.delegate searchBar:searchBar selectedScopeButtonIndexDidChange:selectedScope];
    }
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if ([self.delegate respondsToSelector:@selector(textDidChange:)]) {
        [self.delegate textDidChange:searchText];
    }
}

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

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

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self setActive:NO animated:YES];
    [self.searchResultsTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
}

@end