Search code examples
iosobjective-cios7uisearchbardisplaycontrol

IOS7 : uisearchdisplaycontroller always show scope bar


Basically what I'm trying to achieve is to have my scope bar to never disappear.

Environment : IOS 7, storyboard, inside a view controller I have a "search bar and search display controller" and a separate tableview (the searchbar is not inside the table)

Inside the view controller.h

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

Inside the view controller.m

@synthesize candySearchBar;

What I tried : inside a custom search bar class

- (void) setShowsScopeBar:(BOOL) showsScopeBar
{
    if ([self showsScopeBar] != showsScopeBar) {
        [super invalidateIntrinsicContentSize];
    }
    [super setShowsScopeBar:showsScopeBar];

    [super setShowsScopeBar: YES]; // always show!

    NSLog(@"setShowsScopeBar searchbar");
    NSLog(@"%hhd", showsScopeBar);
}

and

searchBarDidEndEditing

Same thing in the view controller, but then

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [candySearchBar setShowsScopeBar:YES];
    [candySearchBar sizeToFit];
}

I hope my question is clear, I tried many solutions posted all over the internet, most of them talk about the setshowsscopebar, but it doesn't seem to work. The output of the log in setshowscopebar is 1, but the scopebar is still not shown.

I still consider myself to be new to the code, the fault can still be a newbie mistake.

edit : another piece of code in the view controller, as you can see i'm searching blind:

-(void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller{
    self.searchDisplayController.searchBar.showsCancelButton = YES;
    self.searchDisplayController.searchBar.showsScopeBar = YES;
    controller.searchBar.showsScopeBar = TRUE;
    controller.searchBar.frame = CGRectMake(0, 149, 768, 88);
    UIButton *cancelButton;
    UIView *topView = self.searchDisplayController.searchBar.subviews[0];
    for (UIView *subView in topView.subviews) {
        if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
            cancelButton = (UIButton*)subView;
        }
    }
    if (cancelButton) {
        //Set the new title of the cancel button
        [cancelButton setTitle:@"Cancel" forState:UIControlStateNormal];
        [cancelButton setEnabled:YES];
        controller.searchBar.showsScopeBar = YES;
        //candySearchBar.scopeButtonTitles = [NSArray arrayWithObjects:@"Flags", @"Listeners", @"Stations", nil];
    }
    NSLog(@"%@",NSStringFromCGRect(controller.searchBar.frame));
    NSLog(@"%@",NSStringFromCGRect(controller.searchBar.bounds));
    NSLog(@"%hhd@",controller.searchBar.hidden);
}

Solution

  • The code you tried will not work in iOS7 onward because apple has changed it behavior of UISearchBar to hide the scope when return to normal view. Add this method to your custom searchBar class.

    -(void)layoutSubviews
    {
        [super layoutSubviews];
        if([[UIDevice currentDevice].systemVersion floatValue]>=7.0) {
             //Get search bar with scope bar to reappear after search keyboard is dismissed
             [[[[self.subviews objectAtIndex:0] subviews] objectAtIndex:0] setHidden:NO];
             [self setShowsScopeBar:YES];
         }
    }
    

    Directly accessing object at index may crash the app in iOS6 because of difference in view hierarchy between iOS6 and iOS7, to avoid this, add this inside if condition only when its iOS7.

    In addition this is also required in the custom search bar class

    -(void) setShowsScopeBar:(BOOL)showsScopeBar {
        [super setShowsScopeBar:YES]; //Initially make search bar appear with scope bar
    }