1

I want to change text in UISearchBar, but I don't want to call performSearch. I could cancelled the selector in two ways.

First way: I'm using method func1.

@property (nonatomic, retain) IBOutlet UISearchBar *searchBar;
-(void) func1
{
  self.searchBar.delegate = self;
  self.searchBar.text = @"";
  [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(performSearch:) object:nil];
}

- (void)searchBar:(UISearchBar *)searchBar_ textDidChange:(NSString *)searchText
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(performSearch:) object:nil];
    [self performSelector:@selector(performSearch:) withObject:nil afterDelay:1];
} 

Second way: I'm using func2

-(void) func2
{
  self.searchBar.delegate = nil;
  self.searchBar.text = @"";
  self.searchBar.delegate = self;
}

Do I have a 100% guarantee that I cancelled the selector in the func1? Is func2 better?

UPDATE: I'm looking for universal solutions, not just self.searchBar.text = @""; or self.searchBar.text = @"Restaurants";.

Mac_Cain13
  • 3,611
  • 2
  • 24
  • 38
Voloda2
  • 12,359
  • 18
  • 80
  • 130
  • Why don't check if searchText is empty in searchBar:textDidChange:? That way you don't even need to call the selector performSearch. – ian Dec 05 '11 at 15:26

3 Answers3

3

First method is quite complicated, you're calling methods and try to cancel them. If the cancel doesn't arrive at the right time the method will be called. So don't do this it's a nightmare if the App grows and situations get more complex.

The second solution is somewhat more robust, you are removing the delegate. So it's guaranteed that the delegate won't get called, because it isn't there. But iOS is also not able to call the delegate for other things that you maybe want to handle. Besides that; You should test this on a device, because I think iOS will remove all results when there is no delegate that returns any results. But this will depend on how you've implemented other parts of the search.

My advice: Implement the searchDisplayController:shouldReloadTableForSearchString: method from the UISearchDisplayDelegate protocol. From this method you can control if the searchbar should reload the table with search results. Right before you alter the search string yourself set a flag, so this method nows when to return what.

Example pseudocode:

BOOL ignoreChanges = NO;

-(void)editSearchString
{
    ignoreChanges = YES;
    self.searchBar.text = @"some_string";
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
{
    BOOL shouldReload = !ignoreChanges;
    ignoreChanges = NO;

    return shouldReload;
}

This way you ignore the change of the search string that is done by your code, but you will respect changes made by the user. It is of course possible to place the check on the ignoreChanges boolean in another function, like the searchBar:textDidChange: method if that suits your needs better then my suggestion!

Good luck!

Mac_Cain13
  • 3,611
  • 2
  • 24
  • 38
0

Try to look up Subclassing NSOperation to be concurrent and cancellable

with BJ Homer answer that explain well how to solve it

hope it helps you!

Community
  • 1
  • 1
Sakares
  • 606
  • 12
  • 31
0

To answer the question you phrased: yes. I've never had trouble with cancelPreviousPerformRequestsWithTarget: not doing what it's supposed to do.

But I'd lean towards the ignoreChanges approach rather than posting and cancelling messages.

David Dunham
  • 8,139
  • 3
  • 28
  • 41