1

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);
}

4 Answers4

5

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
}
mike56
  • 3
  • 1
CoolMonster
  • 2,258
  • 25
  • 50
  • Thankyou!!! After a little bit of playing around with you code, the trick was to uncomment the one line of code and maintain the rest. This returned the desired result :D – msec Jan 20 '14 at 12:11
  • @msec Ok i made edit to my code. to use the commented line alone to be more clear. Be sure that line will only work in ios7. – CoolMonster Jan 20 '14 at 12:14
  • I edited again but it still has to go through review. You removed one of the required lines of code, I also inserted brackets that were missing for the if statement. In addition, I added all other necessary code – msec Jan 20 '14 at 12:35
  • @msec I think better keep it clear as the question state to show Scope bar not all other edits u made are not necessary for this question. – CoolMonster Jan 20 '14 at 12:38
  • @msec there is no necessary for that line man.Can u please check that without that line – CoolMonster Jan 20 '14 at 12:55
  • I have checked, you need the line of code. mike56 also tried and has indicated the same result from his end too – msec Jan 22 '14 at 10:20
0

I have the same issue. Perhaps it is something that has changed in iOS7 since showing the scope bar is supposed to be the default behaviour. You can verify this in the section "Creating an Optional Scope Bar to Filter Results" of the following tutorial:

http://www.raywenderlich.com/16873/how-to-add-search-into-a-table-view

Hopefully someone has a solution for this; otherwise we will have to look for a workaround.

Neoluis10
  • 1
  • 1
  • 4
0

initialize set scope bar NO

[self.searchBar setShowsScopeBar:NO];
[self.searchBar sizeToFit];

//default scope bar selection
self.searchBar.selectedScopeButtonIndex=3;

unselect/remove tick from scopeBar checkbox

enter image description here

codercat
  • 22,873
  • 9
  • 61
  • 85
  • This doesn't seem to work, are you sure that this will SHOW the scope bar and keep it shown even after cancelling a search? – msec Jan 18 '14 at 05:31
  • you are messed up your searchDisplayControllerDidEndSearch. actually what you want or what you tried to do – codercat Jan 18 '14 at 05:43
  • If you could give me a sample project that would be greatly appreciated, i have tried your code in various methods and can't seem to get it to work the way I want it to. I am using both a tab and nag bar if that makes any difference – msec Jan 18 '14 at 06:30
  • xib @iDev, i was able to get it to appear at first by subclassing UISearchBar and using this code `- (void) setShowsScopeBar:(BOOL)showsScopeBar { [super setShowsScopeBar:YES]; //Always show scope bar }` but this only works until I activate the search bar. Once I clear the search the scope bar gets hidden and I can't seem to get it back – msec Jan 18 '14 at 06:38
  • https://github.com/iDevAndroid/TestSearchDisplayController this for storyboard if you want exactly from xib let me know – codercat Jan 18 '14 at 06:40
  • I just downloaded your test app, in your app I have to first click on the search bar for the scopeBar options to become visible. This is not what I want. I want the scopeBar options to always be visible below the searchBar regardless of whether the keyboard is active or not. @iDev – msec Jan 18 '14 at 07:01
  • you want always visible the scope bar below searchbar is it – codercat Jan 18 '14 at 07:17
  • I just added a pull request to your project, it will give you an idea of what I am trying to achieve. I'm almost there except once I click on the search bar and then cancel it, my scope bar goes away @iDev – msec Jan 18 '14 at 08:53
0

It's possible (but hacky) to do this without a custom searchBar, in a pretty similar way to what CoolMonster suggests.

In your TableViewController, this will show the ScopeBar after a search ends:

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
    //Show the scopeBars
    controller.searchBar.showsScopeBar = YES;

    //Resize the searchBar to show ScopeBar
    controller.searchBar.frame = CGRectMake(0, 0, 320, 88);

    if([[UIDevice currentDevice].systemVersion floatValue]>=7.0) {
        [[[[controller.searchBar.subviews objectAtIndex:0] subviews] objectAtIndex:0] setHidden:NO];
    }
}

Then, since you probably want it to appear before you search, add this line to the TableViewController's viewDidLoad:

    [self searchDisplayControllerDidEndSearch:self.searchDisplayController];

For the record, after getting this to work, I ended up using a separate segmented control instead of the approach above for several reasons, not least of which was that touching the ScopeBar of a SearchBar, once you get it to display, launches the search display tableView, which makes of sense if you're using it the recommended way. However, since I wanted the ScopeBar to work without launching the search tableview, for me it made more sense just to use my own segmented control and add it to my tableHeaderView under the searchBar.

riocordero
  • 119
  • 1
  • 5