4

If you look closely to the bottom of the UISearchBar in a UISearchDisplayController, you'll notice it has a subtile drop shadow. This shadow doesn't fit in the design of the app I'm currently working on, so I'm trying to remove/hide it. Unfortunately I have not yet succeeded.

During my research into this drop shadow, I found that it's not part of the UISearchBar. When I remove the UISearchDisplayController's UISearchBar from its superview in - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller, the shadow remains visible.

The shadow turned out to be part of the UISearchDisplayController's searchResultsTableView: when I hide the searchResultsTableView, the shadow disappears. However, I have not been able to trace down the view that has the shadow on its layer. I tried recursively iterating through all visible views (starting at [[UIApplication sharedApplication] window]) and then hiding the drop shadow of each view and setting its clipsToBounds property to YES, which also did not yield the desired result.

Any ideas?

datwelk
  • 1,017
  • 1
  • 9
  • 18

2 Answers2

3

I finally found a solution. Since setting clipsToBounds to YES and hiding the drop shadow of each view in the hierarchy didn't work, it's obvious that the shadow is an image. After iterating through all subviews of the searchResultsTableView and printing their class property, I found an instance of _UISearchBarShadowView, which obviously is the culprit. So what I'm doing now is finding the _UISearchBarShadowView and setting its alpha to 0.0f.

- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
    [self _findAndHideSearchBarShadowInView:tableView];
}

- (void)_findAndHideSearchBarShadowInView:(UIView *)view
{
    NSString *usc = @"_";
    NSString *sb = @"UISearchBar";
    NSString *sv = @"ShadowView";
    NSString *s = [[usc stringByAppendingString:sb] stringByAppendingString:sv];

    for (UIView *v in view.subviews)
    {
       if ([v isKindOfClass:NSClassFromString(s)]) {
            v.alpha = 0.0f;
        }
        [self _findAndHideSearchBarShadowInView:v];
    }
}
datwelk
  • 1,017
  • 1
  • 9
  • 18
1

The accepted answer uses a private API, which could get your app rejected. Instead, I'd just locate and hide any subviews that are also custom subclasses of UIImageView, like so:

- (void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView
{
    for (UIView *view in tableView.subviews) {
        if ([view.class isSubclassOfClass:[UIImageView class]]) {
            view.alpha = 0.f;
        }
    }
}
followben
  • 9,067
  • 4
  • 40
  • 42
  • This is more dangerous than the answer using private API, since Apple may change the UITableView view hierarchy and add another UIImageView subclass, which will be hidden by this method then as well. Moreover, it is unlikely that the private API usage will be detected by Apple, since the culprit's class name is composed dynamically during runtime (see: http://stackoverflow.com/a/13387866/21698). – datwelk May 19 '13 at 12:55
  • The scroll bars are UIImageViews and `isSubclassOfClass` returns YES for them. Also, you might have custom table header/footer views which are also UIImageViews (or derived from them). I added an extra check that the frame's origin was (0,0) to avoid the false positives. – Geoff Hackworth Jul 05 '13 at 09:27