30

In the UIViewController documentation about the searchDisplayController property 1 it says:

If you create your search display controller programmatically, this property is set automatically by the search display controller when it is initialized.

And when I create my UISearchDisplayController thusly:

[[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self] autorelease];

-[UIViewController searchDisplayController] is not nil. However, it is nilled out after the event loop finishes, which causes the search display controller not to show when I touch inside the search bar. Nothing crashes. This is very weird. If I omit the call to autorelease, everything works:

[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];

However, leaks the UISearchDisplayController (I verified this with Instruments). Since the searchDisplayController property is marked as (nonatomic, retain, readonly) I expect that it would retain the UISearchDisplayController after it is set.

This stackoverflow article is related.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Heath Borders
  • 30,998
  • 16
  • 147
  • 256

2 Answers2

52

I've run into the same thing. I create all of my controllers/views programmatically. Everything was working fine until I converted my project to use ARC. Once I did the UISearchDisplayControllers were no longer retained and the searchDisplayController property in each UIViewController was nil after the run loop ended.

I don't have an answer why this is happening. The Apple docs suggest that the SDC should be retained by the view controller but this is clearly not happening.

My solution was to create a second property to retain the SDC and I nil it when I unload the view. If you are not using ARC you need to release mySearchDisplayController in viewDidUnload and dealloc. Otherwise this is good as is.

In MyViewController.h:

@property (nonatomic, strong) UISearchDisplayController * mySearchDisplayController;

In MyViewController.m:

@synthesize mySearchDisplayController = _mySearchDisplayController;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // create searchBar
    _mySearchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
    _mySearchDisplayController.delegate = self;
    _mySearchDisplayController.searchResultsDataSource = self;
    _mySearchDisplayController.searchResultsDelegate = self;
    // other stuff
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    _mySearchDisplayController = nil;
    // other stuff
}
Bob Spryn
  • 17,742
  • 12
  • 68
  • 91
XJones
  • 21,959
  • 10
  • 67
  • 82
  • I like this answer, but I would prefer an official-ish link from documentation. If you can provide either a mailing list link or something in the docs to back up your point, I'll be happy to accept the answer. – Heath Borders Oct 31 '11 at 19:55
  • Your method is what I ended up doing as well. – Heath Borders Oct 31 '11 at 19:56
  • 4
    Was just trying to help. I've seen nothing official regarding this. It's just obviously either broken or mis-documented as we both discovered. – XJones Oct 31 '11 at 19:59
  • It is very helpful. I'm sorry if I didn't come across as appreciative. – Heath Borders Nov 01 '11 at 02:56
  • No worries. I'm not so concerned with SO points. SO has saved me immense amount of time so I give answers when I can. FWIW, I submitted a bug to Apple on this. If I get a response I'll post it here. – XJones Nov 01 '11 at 15:58
  • Awesome. That's exactly what I'm looking for. If you just want to add the bug to openradar and post a link, I'll accept. – Heath Borders Nov 01 '11 at 19:37
  • Looks like you beat me to it on openradar. I'll let you know if I hear anything from apple. – XJones Nov 01 '11 at 21:50
  • 1
    I've just run into this with ARC too. @XJones be great if you could post the openradar number here. In the meantime, I guess I'm upvoting this answer :) – followben Nov 02 '11 at 21:26
  • 3
    Two years later, you're still helping people figure this out! Thank you so much. I had no idea why mine wasn't working. – Eric Amorde May 23 '13 at 04:21
  • 1
    Agreed. Can't believe this hasn't been resolved. I just wasted an hour on this very thing. Thanks for confirming my sanity. – Jason McCreary Jun 17 '13 at 15:21
  • 4
    Still in iOS 7. Duped. – an0 Sep 13 '13 at 03:42
3

The solution above works just fine, but I also found that you can use

[self setValue:mySearchDisplayController forKey:@"searchDisplayController"]

in the context of a UIViewController subclass.

  • 2
    That may work , but it's not consistent. Apple can choose to change the name of that key in the future SDKs. The accepted answer seems to be the best one. – George Apr 06 '12 at 11:51