How to Throttle Search (Based on Typing Speed) in iOS Uisearchbar

How to throttle search (based on typing speed) in iOS UISearchBar?

Thanks to this link, I found a very quick and clean approach. Compared to Nirmit's answer it lacks the "loading indicator", however it wins in terms of number of lines of code and does not require additional controls. I first added the dispatch_cancelable_block.h file to my project (from this repo), then defined the following class variable: __block dispatch_cancelable_block_t searchBlock;.

My search code now looks like this:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if (searchBlock != nil) {
//We cancel the currently scheduled block
cancel_block(searchBlock);
}
searchBlock = dispatch_after_delay(searchBlockDelay, ^{
//We "enqueue" this block with a certain delay. It will be canceled if the user types faster than the delay, otherwise it will be executed after the specified delay
[self loadPlacesAutocompleteForInput:searchText];
});
}

Notes:

  • The loadPlacesAutocompleteForInput is part of the LPGoogleFunctions library
  • searchBlockDelay is defined as follows outside of the @implementation:

    static CGFloat searchBlockDelay = 0.2;

Live search throttle in Swift 3

Your error was because you probably forgot the #selector() part.

Here's how it should look:

func searchBar() { 
NSObject.cancelPreviousPerformRequests(withTarget: self,
selector: #selector(self.getSearch(completed:searchString:)),
object: nil)

perform(#selector(self.getSearch(completed:searchString:)),
with: nil, afterDelay: 0.5) }

You get the error because you didn't enclose your function in #selector

Now, as for the arguments, here's a function for that:

perform(#selector(getSearch:completion:searchString), with: <some completion>, with: "search string")

Search word by word to API

An effective way to do this is to monitor how long of a delay there is between user input, and only request to the server after the user has stopped typing for x amount of time.

For instance, the user types 'B' and waits 0.05 seconds then types 'o' and waits 0.08 seconds then types 'y' and stops typing.

If your code only submits to the server after there has been at least 0.5 seconds between character input, it will only request to the server once, after "Boy" has been entered.

How to detect that textDidChange: on UISearchBar was triggered by dictation

I had the same problem: detect that speech dictation is still running and processing the voice input.

It's exactly like you are describing: from the textDidChange you get an empty NSString with length=1

In my case, my solution was to take the first char of the text (if available) and check it's integer value. Apparently, the value of the "processing voice input" is always -17,

I know that is not a perfect solution, but it works. If someone has a better solution, please share it :)

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
BOOL atLeastOneChar = searchText.length > 0;
BOOL speechRecognitionOngoing;

if (atLeastOneChar) {
// Checking if the user used the dictation feature.
// A char of value -17 is always returned as text while processing the voice.
// So if the first char is == -17 it means the dictationg is going on.

const char firstChar = *text.UTF8String;
NSInteger processingDictationSpeechChar = -17;
if (firstChar == processingDictationSpeechChar) {
// --> speech recognition is ongoing!
speechRecognitionOngoing = YES;
}
}
}

iOS: Wait until user finishes typing and then send request

Add a small delay before sending the request, and then cancel that delayed request if the user continues typing

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];

[self performSelector:@selector(sendSearchRequest) withObject:searchText afterDelay:0.1f];
}

you may need to adjust the delay time. too long and its noticeable to the user that there is a delay, too short and you have the same problem as now

Make UISearchBar to search on two different fields

There is a easy way to filter your array where you could decide completely when a object of the array should be in the new array or not:

data = data.filter({( aObject: YourClass) -> Bool in

// code for checking if the aObject should be in the data array
// then return true if it should be in the new array and false if not
// For example your return statement could be something like this:

return (aObject.firstString.lowercaseString.rangeOfString(searchText.lowercaseString) != nil) || (aObject.secondString.lowercaseString.rangeOfString(searchText.lowercaseString) != nil)
})

IOS: Autocomplete Search using UISearchbar

There are many logic but i put my logic here :

Take Two NSMutableArray and add one array to another array in ViewDidLoad method such like,

self.listOfTemArray = [[NSMutableArray alloc] init]; // array no - 1
self.ItemOfMainArray = [[NSMutableArray alloc] initWithObjects:@"YorArrayList", nil]; // array no - 2

[self.listOfTemArray addObjectsFromArray:self.ItemOfMainArray]; // add 2array to 1 array

And Write following delegate Method of UISearchBar

- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText
{
NSString *name = @"";
NSString *firstLetter = @"";

if (self.listOfTemArray.count > 0)
[self.listOfTemArray removeAllObjects];

if ([searchText length] > 0)
{
for (int i = 0; i < [self.ItemOfMainArray count] ; i = i+1)
{
name = [self.ItemOfMainArray objectAtIndex:i];

if (name.length >= searchText.length)
{
firstLetter = [name substringWithRange:NSMakeRange(0, [searchText length])];
//NSLog(@"%@",firstLetter);

if( [firstLetter caseInsensitiveCompare:searchText] == NSOrderedSame )
{
// strings are equal except for possibly case
[self.listOfTemArray addObject: [self.ItemOfMainArray objectAtIndex:i]];
NSLog(@"=========> %@",self.listOfTemArray);
}
}
}
}
else
{
[self.listOfTemArray addObjectsFromArray:self.ItemOfMainArray ];
}

[self.tblView reloadData];
}
}

Output Show in your Consol.

This code might helpful for you.



Related Topics



Leave a reply



Submit