5

Ok, I'm pulling my hair out over this. I'm almost certain I had this working at one point too, and now it isn't working.

I have a UISearchBar embedded in a table view cell. I have the search bar declared as a property, my view controller is set up as a UISearchBarDelegate. Search bar is initialized, configured, everything looks great. It is responding to the other delegate methods to restrict characters entered, handle the cancel button, everything but searchBarSearchButtonClicked. What the hell am I doing wrong?

Here is the basics of my setup:

ViewController.h

    @interface SearchMLSNumberViewController : UIViewController <UISearchBarDelegate>

    @property (strong, nonatomic) UISearchBar *searchField;

ViewController.m

// viewDidLoad
// init the search bar
self.searchField = [[UISearchBar alloc] init];
self.searchField.delegate = self;
self.searchField.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchField.placeholder = NSLocalizedString(@"Search", @"Search");

// in my cell setup
CGRect frame = cell.contentView.frame;
[self.searchField setFrame:frame];
[cell.contentView addSubview:self.searchField];

// here is the delegate call that never fires for me
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    NSLog(@"search button pressed");
}

I've excluded all my tableview setup and all that, it all seems to be working fine. That is what is killing me. Everything is working just fine, all the other delegate methods... except the search button return. Please tell me I'm doing something stupid. I'm out of options.

UPDATE I have figured out the culprit of why the search button fails to execute. I removed all of my other search bar delegate methods and it started working... so I commented them all out until I found out which one was causing problems.

This guy is my culprit:

- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSCharacterSet *invalidCharSet = [[NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ,-"] invertedSet];
    NSString *filtered = [[text componentsSeparatedByCharactersInSet:invalidCharSet] componentsJoinedByString:@""];
    return [text isEqualToString:filtered];
}

So now, does the search button actually count as a key press and I need to add it to my allowed characters? Or do I need to add a check for it so it is allowed to return? Any help would be great.

UPDATE 2 I've solved my problem. It took a combination of clues and revelations, but I finally got it working. The culprit was not allowing the return key in the character set. I added \n to the character set and voila, the search button was not working correctly. Here is my updated filter logic to show the return key added, as well as the valid character set for my situation. I will answer this myself once I'm allowed.

- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSCharacterSet *invalidCharSet = [[NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ,-\n"] invertedSet];
    NSString *filtered = [[text componentsSeparatedByCharactersInSet:invalidCharSet] componentsJoinedByString:@""];
    return [text isEqualToString:filtered];
}
Bill Burgess
  • 14,054
  • 6
  • 49
  • 86
  • So take your solution, make it an answer, and select it as the answer so others (like me) don't go reading this looking to help. – David H Nov 14 '13 at 14:35
  • Two things: 1) `NSCharacterSet -invertedSet` is expensive, so you might want to consider caching `invalidCharSet` as a static constant, and 2) a better approach might be to use CFStringTransform to at least strip accents & diacritics first, so that user input can be more lenient. – mattt Nov 14 '13 at 14:36
  • David H - I will just as soon as SO let's me. Unfortunately, I answered my self too quickly. You should have read that in my update and move on instead of wasting your time adding a snarky comment. – Bill Burgess Nov 14 '13 at 21:55
  • @mattt - Thanks for the info, I'll definitely update that to a static constant. As far as the character set, it is for a customer and those are the only values allowed. – Bill Burgess Nov 14 '13 at 21:56

1 Answers1

12

I'm answering my own question here so I can close things out. I ended up resolving this issue shortly after asking the question. Funny how that work. The answer is relevant to other users, so I'll update my answer for posterity.

The tl;dr is that I was not allowing the return key in -shouldChangeTextInRange. I had a limited set of characters that are allowed to entered, and I forgot to include the return key as a valid character.

- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSCharacterSet *invalidCharSet = [[NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ,-\n"] invertedSet];
    NSString *filtered = [[text componentsSeparatedByCharactersInSet:invalidCharSet] componentsJoinedByString:@""];
    return [text isEqualToString:filtered];
}

This could also come into play if you are limiting characters within a text field as well. That is how I ended up solving my issue. I started by removing all my delegate methods until I found out which one was blocking me. Once I figured out what I was doing, I tracked down the return key by searching against text field issues. There weren't a lot of issues out there for the search bar, which is why I ended up asking this question. I may have figured this out without asking the question, but at least I learned something and hopefully this answer will help someone else out in the future.

Also, thanks to @mattt for the advice on better ways to restrict characters and thinking about the overall health of my code base.

Bill Burgess
  • 14,054
  • 6
  • 49
  • 86
  • Wow nice catch, this drove me mad for about 5 minutes until I found your answer. I was also restricting the character set. – sweepez Mar 07 '18 at 22:21