8

I'm trying to recreate this UISearchBar (as seen in the Table Search example code):

alt text http://img168.imageshack.us/img168/6378/43558113.png

All the examples I've seen to do this involve using a xib, however I need to do it programmatically. The problem is changing the tint color also changes the cancel button's tint:

alt text http://img243.imageshack.us/img243/1375/screenshot20100527at944.png

Any ideas?

christo16
  • 4,843
  • 5
  • 42
  • 53

3 Answers3

17

Associating the search bar with a UISearchDisplayController magically provides a lot of standard look and behavior such as:

  • gray tint without affecting cancel button
  • auto showing/hiding of cancel button
  • width adjustment around any tableview indexes

In my tableview controller I've done the following:

- (void)viewDidLoad {
    [super viewDidLoad];

    // setup searchBar and searchDisplayController

    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
    [searchBar sizeToFit];
    searchBar.delegate = self;
    searchBar.placeholder = @"Search";
    self.tableView.tableHeaderView = searchBar;

    UISearchDisplayController *searchDC = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];

    // The above assigns self.searchDisplayController, but without retaining.
    // Force the read-only property to be set and retained. 
    [self performSelector:@selector(setSearchDisplayController:) withObject:searchDC];

    searchDC.delegate = self;
    searchDC.searchResultsDataSource = self;
    searchDC.searchResultsDelegate = self;

    [searchBar release];
    [searchDC release];
}
Scott McCammon
  • 1,865
  • 16
  • 10
  • Check also Joris Kluivers answer about overwriting searchDisplayController – JOM Jan 05 '11 at 22:05
  • 2
    In case anyone is thinking of using this -- my app just got rejected for using non-public APIs. setSearchDisplayController was the culprit. – serverpunk Apr 22 '12 at 18:31
16

I totally agree with Scott McCammon.

However using a performSelector:withObject: on setSearchDisplayController: would not be my approach. This depends on private API which can change at any moment. If Apple would remove their private implementation your app will crash.

A better way would be to override the searchDisplayController: in your view controller to return your instance of UISearchDisplayController:


- (UISearchDisplayControlelr *) searchDisplayController {
    return yourInstanceOfASearchController;
}
Joris Kluivers
  • 11,894
  • 2
  • 48
  • 47
1

I don't understand the need for the call to setSearchDisplayController: or the override for searchDisplayController. Under iOS 4.3.2 initWithSearchBar:contentsController: appears to set searchDisplayController for the UIViewController instance passed as the contentsController argument. Perhaps this was a problem in earlier iOS releases, but it appears redundant in the current release.

rich
  • 201
  • 1
  • 9
  • 2
    I did some more testing. searchDisplayController is getting assigned, but not retained as noted by Scott McCammon above. Rather than call the undocumented API, I'm saving a retained reference in an instance variable and then releasing it in dealloc. – rich May 05 '11 at 21:46
  • Ditto for me. I use 3 private instance variables on the .m file: UISearchBar* searchBar; NSArray* filteredList; UISearchDisplayController* searchController;. Under ARC, I don't believe you need to nil them out in a 'dealloc' but I'm no expert. When combining iOS 4 & ARC, you need to nil out weak references, but regular (strong) references are automatically nil'ed out. – Basil Bourque Jan 31 '13 at 02:25
  • it's apparently best practice to use properties for objects such as UISearchDisplayController let alone most objects in general. In fact, I couldn't get my SDC working unless I declared a property. So I used Scott McCammon's code and instead of locally declaring the SDC I made a private property for it. – mafiOSo Oct 15 '13 at 11:49