If you want to provide instant query suggestions to users as they type in text fields, Google’s Autocomplete suggestions—also known as search suggest, autosuggest, or incremental search—grants your applications this power. This article outlines my experience implementing Google’s unofficial Autocomplete API with the EBSCO Discovery Service search feature in Grant MacEwan University Library’s iPhone app (available free in the iTunes App Store).
Autocomplete API Introduction
Introduced in September 2010, Google Autocomplete is a Google Instant feature that automatically displays a list of algorithmically-generated popular search suggestions to choose from as the user types a query. Autocomplete’s predictions are helpful as they reduce the amount of typing required, they forgive entry errors and catch common spelling mistakes, and they inspire new keywords for the user to explore while refining a search.
Thanks to an unofficial, undocumented REST API, this fantastic feature can be implemented in any web-enabled applications. The base URL:
1 http://google.com/complete/search?
The Output parameter:
1 output=result_type
Where result_type can be either set for generic browser toolbars (output=toolbar) which results in detailed XML output containing both query suggestions and their number of hits on a Google search, or set to for Mozilla Firefox’s search bar (output=firefox) which results in lightweight JSON output returning the original query and an array of query suggestions (without the number of hits). Unfortunately, detailed JSON results (output=json) have been disabled by Google. I have yet to discover any other active output_type settings. The Query parameter:
1 q=search+terms
Where search+terms is a URL-encoded query string. Full URL example: To get autocompletions for “John Stuart” returned in XML one would use the following URL:
1 http://google.com/complete/search?output=toolbar&q=John+Stuart
By default the API returns up to ten suggestions. I have yet to discover parameters for setting the number of results or for limiting by location or time range. If you discover any additional URL parameters that I haven’t documented, please leave comments and I’ll credit your contributions. I have not performed any API stress testing and I have found no usage documentation, but I would assume that there must be a daily or hourly per-IP request rate limit. Unless your users are performing hundreds of searches per day I doubt this would become an issue. The Google Autocomplete API is not an official public Google API so use it wisely as future support not guaranteed. Several Google Toolbars make use of this API so I’d like to think Google won’t just discontinue it, but they set a worrying precedent when they disabled their unofficial Weather API without warning.
Alternative APIs
If you prefer to not use Google’s unsupported API, Bing and Yahoo offer their own unofficial alternatives:
Bing RelatedSearch
Bing offers a nice, simple JSON-response suggestion API that produces output similar to that of Google when using output=firefox:
1 http://api.bing.com/osjson.aspx?query=John+Stuart
Yahoo Related Suggestions service
Yahoo has deprecated their Related Suggestions service as of February 2011; however, it still seems to work using “appid=YahooDemo”:
1 http://search.yahooapis.com/WebSearchService/V1/relatedSuggestion?appid=YahooDemo&query=neil
This API is quite flexible as it enables JSON output by adding the “output=json” parameter and it can return up to 50 results instead of the default 10 (eg. “results=25”). The API is limited to 5,000 queries per IP address per day for noncommercial purposes. Before implementing this API, one should be wary of the possibility of an undisclosed rate limit on the YahooDemo App ID; I would suggest investigating how to obtain a distinct App ID and then test whether or not it functions with the Related Suggestion service.
Implementing Autocomplete in Objective-C for iOS
The general implementation strategy involves displaying a UITableView of selectable query suggestions below a UISearchBar. Every time the user alters their query, an Autocomplete request is performed to refresh suggestion data. First, set up your view with a UISearchBar (_searchBar), a UITableView (_tableView), and an NSArray (_suggestionArray). Assign _tableView’s dataSource in order to set it up with content from the _suggestionArray:
1 #pragma mark - UITableViewDataSource Methods
2
3 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
4 return _suggestionArray.count;
5 }
6
7 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
8 static NSString *CellIdentifier = @"Cell";
9
10 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
11 if (cell == nil) {
12 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
13 }
14
15 cell.textLabel.text = [_suggestionArray objectAtIndex:indexPath.row];
16 return cell;
17 }
Assign _tableView’s delegate in order to capture touch events and assign the _searchBar text:
1 #pragma mark - UITableViewDelegate Methods
2 - (void)tableView:(UITableView *)tableView:(NSIndexPath *)indexPath {
3 _searchBar.text = [_suggestionArray objectAtIndex:indexPath.row];
4 }
Optionally, you may also set the _tableView to disappear or a search to be performed when a cell is tapped—it all depends on your desired user experience. Now you must capture every UISearchBar text change event by assigning _searchBar’s delegate and then implement the following UISearchBarDelegate method:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
Every time searchBar:textDidChange: is called and the searchText isn’t empty:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
-
URL-encode the searchText by replacing spaces with pluses, eg.:
and by replacing symbols with percent-escapes:
[searchText stringByReplacingOccurrencesOfString:@" " withString:@"+"];
[searchText stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
-
Construct a request NSURL, eg.:
[NSURL URLWithString:[NSString stringWithFormat:@”http://google.com/complete/search?output=toolbar&q=%@”, searchText]];
- Using the resulting URL, perform an Autocomplete API request using your favourite HTTP request class such as NSURLConnection or AFNetworking.
- Upon request success, parse the result data into an array of suggestions. Each suggestion may be stored as a string or a dictionary depending on how much detail you wish to capture from the data. For XML, Apple provides NSXMLParser. For JSON, I suggest using JSONKit, a third-party library.
- Assign the new array of suggestions to _suggestionArray and then call [_tableView reloadData];
If the searchText is empty, simply set your suggestion array to nil and then call [tableView reloadData]; Now you should have a working, rapid-responding implementation of Google Autocomplete within your iOS app! While you could implement all of this code within a single UIViewController class, I suggest creating an AutocompleteRequest object that contains your API HTTP request and a SuggestionSearchView object that contains your _searchBar and _tableView for modular, easy to read code. Here is a screenshot of this feature in action on the MacEwan Library app (available free in the iTunes App Store):