6

I have a list of things provided by the system (e.g. brands) which are not user editable but have to change from time to time.

Context

These things are displayed in a table view and are searchable using the default UISearchDisplayController. However, as the list of things surely isn't complete I want to give users the ability to request the addition of other things to the list. To do so I added a table footer view to both the original table view and the search results table view, which provides a button to send a mail.

Problem

It works fine as long as the search results table view still contains entries. My table footer view is displayed below the search results and everything is fine.

However, if no results are found for a search term, the search display controller displays a "no result" label centered over the table view. This usually looks great, like this:

default "no results" screen

But since my tableFooterView is still displayed (which I want it to be!) the "no results" label overlaps my footer view and it looks crappy:

enter image description here

I think in my case I don't need the "no result"s label, since my footer view makes it reasonable clear that there are no results and what to do about it. I don't mind it either, as long as it doesn't overlap.

Question

How can I either

  • make the search view not display the "No Results" label
  • or configure how it is displayed (-> not overlapping)

If this is not possible I'm also open to suggestions for others ways of displaying the footer view (not as footer), which would not have this problem. But I like the solution since I can use it in both cases (normal table view and search results table view) without having to change anything.

Community
  • 1
  • 1
Joachim Kurz
  • 2,875
  • 6
  • 23
  • 43
  • User UISearch bar instead of UISearchDisplayController. – Vineesh TP Apr 07 '14 at 04:07
  • I'm actually using both. ;-) But if I used just the UISearchBar I would have to do all the stuff myself, that the UISearchDisplayController currently does for me. (like overlaying another table view, providing cancel functionality, etc.) I like almost everything the search display controller does, event for this one thing, so I'd prefer it if I could keep it. – Joachim Kurz Apr 07 '14 at 09:47
  • @ Joachim Kurz: Check my answer. – Vineesh TP Apr 08 '14 at 03:37
  • i am also have the same type of method to add the place if places are not there mr. joachim kurz can u please tell how to add the button and labels in footer search table view. and i am changed the "no results" text. – Hari Narayanan Jun 21 '16 at 12:35

5 Answers5

5

First of all, it is important to keep in mind that using UISearchDisplayController is a trade-off between customizability and convenience. You get a lot of automatic stuff for free, but if you require a lot of customization it might not suit your needs. It works best as a drop-in solution, and if you'd really like to use it, I recommend you work your app around it instead of trying to hack its behavior.

With that said, why don't you make the UITableView return a single row when there are no results? This row could either be empty, display some boilerplate text or an image (sad face or something humorous that matches the app).

Having a single row to be presented, the default "No Results" label from UISearchDisplayController would not be shown. This is the default behavior for a lot of Apps, like Instagram (check out the Explore tab), Kindle and the default Notes.app, although they are probably not using UISearchDisplayController.

If you find that this workaround doesn't fit your app, you could also try making the "Missing a Brand" view into the header view of the first section of the UISearchResultsTableView (instead of the footer view). That way, the "No Results" label would be displayed below it. Combining this idea with a single empty row would even work better.

A third option would be to insert this view on top of the UISearchResultsTableView. This could be done every time there were no results (properly removing it when necessary) or just a single time, using its hidden property to show or hide it instead.

Any other method for hiding this label is probably hacky, like this one: https://stackoverflow.com/a/11715841/382834. Although easier on your current logic, it might have negative consequences later on, so it's possibly the worst path to follow.

Community
  • 1
  • 1
Aloha Silver
  • 1,394
  • 17
  • 35
  • Thanks a lot for several nice suggestions. Always returning one row felt kinda hacky as well. I first thought about adding my MissingBrand-view as an additional cell or section footer but that felt wrong. Bu setting it as the section footer I could be sure it would always be just below the last cell of the table view without having to do extra (potentially error-prone) work. I thought I should keep the state information that there are no results (e.g. for accessibility) and just display some additional UI. – Joachim Kurz Apr 06 '14 at 16:42
  • Regarding the different ideas: The hack is quite jacky, yes. Returning an additional cell is much less error-prone so I'd rather do that. I tried adding it as a table-header view but in that case it is displayed above the "No Results" but the search results aren't displayed anymore. No idea why (all I changed is that I assigned it to `tableHeaderView` instead of `tableFooterView`). – Joachim Kurz Apr 06 '14 at 16:48
  • About the third option: How can I reliably insert the view on top of the search display controllers table view? It is simply overlaid over my view and I have almost no control over it, have I? I couldn't even configure the table view in the Storyboard to specify cells with resuse identifiers it is supposed to use. Or do you mean it should overlap the search results table view, and thus covering it? Not sure whether that would work, as the "No Results" Label seems to float above a lot of stuff. I'll experiment a bit more and let you know what I did, but thanks again for the great suggestions! – Joachim Kurz Apr 06 '14 at 16:52
  • *Joachim*, I actually meant setting the view as a section header, since I originally understood it was also a section footer. I've since edited the post to make this clear - sorry for not having it this way before. Check out the `tableView:viewForHeaderInSection:` method for that. – Aloha Silver Apr 07 '14 at 03:14
  • As for inserting the view above the `UISearchResultsTableView`, I recommend you start experimenting with the delegate method `searchDisplayController:willShowSearchResultsTableView:`. In there you can use `[self.view insertSubview:MISSING_BRANDS_VIEW aboveSubview:tableView];` to place the view. Of course this would be a more general approach, since you wouldn't account for the numbers of rows being presented. Thus, after you're happy with the way it works, move the add/remove code to some method that allows you control over that number, like `tableView:numberOfRowsInSection:`. – Aloha Silver Apr 07 '14 at 03:14
0

Use UISearchBar It will not hide Navigationbar

Import UISearchBar Delegate <UISearchBarDelegate>

Don't forget to connect delegate with your searchbar

[yourSearchbar setDelegate:self]

Then Add these delegate methods,

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
   // Put here in search what you want.
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)aSearchBar
{
    [aSearchBar resignFirstResponder];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
    [searchBar setShowsCancelButton:YES animated:YES];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
    [searchBar resignFirstResponder];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
    [searchBar resignFirstResponder];
}
Vineesh TP
  • 7,755
  • 12
  • 66
  • 130
0

What I did is to detect if there are 0 results. If there are 0 results I changed numberOfRowsInSection to return 1, heightForRowAtIndexPath to return 0 and cellForRowAtIndexPath to return a generic UITableViewCell.

That's it. Footer is shown in all it's glory.

YogevSitton
  • 10,068
  • 11
  • 62
  • 95
0

I'd love to show you my solution.

First I wrote some categories. The first category gives us UISearchDisplayController table.

@interface UITableViewController (YourUITableViewControllerCategory)
- (UITableView *) tableViewSearch;
@end

@implementation UITableViewController (YourUITableViewControllerCategory)
- (UITableView *) tableViewSearch
{
    if ([self respondsToSelector:@selector(searchDisplayController)])
    {
        id searchDisplayController = [self performSelector:@selector(searchDisplayController)];
        if ([searchDisplayController respondsToSelector:@selector(searchResultsTableView)])
        {
            id searchResultsTableView = [searchDisplayController performSelector:@selector(searchResultsTableView)];
            if ([searchResultsTableView isKindOfClass:[UITableView class]]) return searchResultsTableView;
        }
    }
    return [UITableView new];
}
@end

The second category returns an array of subview of certain type.

@interface UIView (YourUIViewCategory)
- (NSArray *) viewsWithClass:(NSString *)class;
@end

@implementation UIView (YourUIViewCategory)
- (NSArray *) viewsWithClass:(NSString *)class
{
    NSMutableArray *array = [NSMutableArray new];
    for (UIView *view in self.subviews)
    {
        if ([view isMemberOfClass:NSClassFromString(class)])
        {
            [array addObject:view];
        }
        [array addObjectsFromArray:[view viewsWithClass:class]];
    }
    return array;
}
@end

Now you are almost ready to search for "No results" label. You have to be sure that all labels in your cells have tag != 0.

- (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    for (UILabel *label in [self.tableViewSearch viewsWithClass:NSStringFromClass([UILabel class])])
    {
        if (label.tag == 0)
        {
            // found it! do whatever you want with label
        }
    }
    return NO;
}

Its just my approach. You can find your own way. Good luck!

iWheelBuy
  • 5,470
  • 2
  • 37
  • 71
0

use the below code to remove the "no result" text value

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
if (!isChangedNoResults) {
    if ([contactManager.filteredPeople count] == 0) {
        [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(changeNoResultsText:) userInfo:nil repeats:YES];
    }
}}

change the text method.

- (void) changeNoResultsText:(NSTimer *)timer {
if (isChangedNoResults) {
    [timer invalidate];
}
else {
    for (UIView *subview in [self.searchDisplayController.searchResultsTableView subviews]) {
        if ([subview isKindOfClass:[UILabel class]]) {
            UILabel *targetLabel = (UILabel *)subview;
            if ([targetLabel.text isEqualToString:@"No Results"]) {
                NSLog(@"Changed!");
                [targetLabel setText:@"_____"];
                isChangedNoResults = YES;
                [timer invalidate];
            }
        }
    }
}

}

or do the below code in search method

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.001);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    for (UIView* v in self.searchDisplayController.searchResultsTableView.subviews) {
        if ([v isKindOfClass: [UILabel class]] &&
            [[(UILabel*)v text] isEqualToString:@"No Results"]) {
            [(UILabel*)v setText:@""];
            break;
        }
    }
});

its really helpful to me,,, try it

Hari Narayanan
  • 754
  • 1
  • 12
  • 36