Using Google Web APIs in a Mac OS X Application
Introduction
Google has some APIs so you can get at their search engine. These APIs are based on SOAP and WSDL, so you can use a number of programming languages with them. For this example, we only care about using Objective C and Mac OS X. I don't care if you don't like square brackets. Get over it, dinosaur.
The API
Whenever someone says something like SOAP, WSDL, or XML-RPC, it's time to pull out the WebServices framework. It's the cat's pajamas. This API does SOAP and XML-RPC. I don't know how all that stuff works. I just know it's a remote procedure call API that uses HTTP, and thanks to WebServices, that's about all I need to know.
When you download the Google Web APIs developer's kit, it comes with a WSDL file. This is some standard format to describe the ins and outs of each API. We can run a WebServices tool on it to convert the WSDL file into an Objective C header and implementation file. The tool can also do C++ or AppleScript, but we're not interested in that now.
What my sample app looks like
This is what the app I wrote looks like. It's a completely useless app. I'm just here to show you how to use the API.
In the top I enter my search terms and my Google Developer Key. The next text field shows the actual result coming back from Google. The next table shows the results in a table. When you click on a result, a summary appears in the bottom text field. Useless app.
How did I do it?
I was reading the online documentation for WebServices and saw it talk about WSDL. The framework does not support WSDL yet, but they have a tool that converts WSDL to source files for you. So this is what I did:
/Developer/Tools/WSMakeStubs -x ObjC -dir ~jav/Projects/GoogleXML/ -file /Volumes/7B85/Users/jav/Desktop/googleapi/GoogleSearch.wsdl
This creates WSStub.* and WSGeneratedObj.*. WSGeneratedObj.* contains generic code, and WSStub.* contains code for the APIs in the WSDL file you gave it.
So now the only code I have to write is the code in my controller class that makes the remote procedure call and put the result in the UI. Here's that function.
// -----------------------------------------------------------------------
// * doSearch
// -----------------------------------------------------------------------
- (IBAction)doSearch:(id)sender
{
// get the query
NSString* query = [searchField stringValue];
// get the Google Developer API key. Dont' use mine, get your own.
NSString* googleKey = [googleDevKeyField stringValue];
// make me one of them WSGeneratedObj just for making the search API call.
// doGoogleSearch is declared in WSStub.h, and is a subclass of WSGeneratedObj.
doGoogleSearch* doSearch = [[doGoogleSearch alloc] init];
// now feed it a bunch of parameters.
[doSearch setParameters:googleKey
in_q:query
in_start:1
in_maxResults:10
in_filter:YES
in_restrict:@""
in_safeSearch:NO
in_lr:@"lang_en"
in_ie:@""
in_oe:@""];
// this performs the actual remote procedure call
NSDictionary* result = [doSearch resultValue];
// put the exact result in the UI so geeks can read it
[resultField insertText:[[doSearch getResultDictionary] description]];
// we're done with this thing
[doSearch release];
// retain the search results so we can populate UI here and there
[searchResults release];
searchResults = [[result objectForKey:@"resultElements"] retain];
// tell our table we have new results
[resultsTable reloadData];
}
I put comments in my code, so I shouldn't have to explain anything more, unless you're not as smart as me.
Download my project
I did all the work, and now you can download free code. Lucky you. Consider sending me money.
Download (68K)
(68K refers to the size of the download. I do not mean to suggest that this code will only compile on the Motorola 68000 series of microprocessors.)
Extreme Mac OS X Programming. Copyright © 2004 John A. Vink