The iOS Client

The TicTacToe iOS client has a simple Master-Detail interface with two different kinds of detail views. The master view is a table view with two sections representing the two different types of detail views: a current games section and a completed games section. As already mentioned, the iOS client relies heavily on the Google APIs client library for Objective-C and the code generated by the endpoints tool to interact with the API backend. One important difference that you may have noticed is that the API backend has three subclasses of the Game base class, while the iOS client only has two classes: a GTLTicTacToeGame class and a GTLTicTacToeScore class. This difference is due to a limitation already discussed on the Modeling the Entities page: many of the API methods take a parameter of type Game and return a value of type Game. The endpoints tool doesn’t realize this is a base class and believes it to be the actual type to use for the object sent to and from the client. The GTLTicTacToeScore class gets created because of the ScoreController that directly deals with Score objects. Because the PendingGame and CurrentGame classes dont add any extra members, this behavior is acceptable for the TicTacToe application.

Even if the PendingGame and CurrentGame classes did add extra members, they would still be retrievable client-side through a method rather than a property. All of the properties on the object returned by the API backend are serialized into JSON before being passed on to the client. Using the JSONValueForKey: method defined in the GTLObject.h header, you can query for the value of a property by a string representing the name specified within your API backend (i.e. a string “date” could be used to retrieve the date property of a GTLTicTacToeGame object). This method can be seen in action in multiple methods in the TTTScoreViewController and in the tableView:cellForRowAtIndexPath: method of the TTTGameListTableViewController with a call to JSONValueForKey:@”outcome”. This method is used because the API backend method getCurrentGameBoard() always returns a Game object to the client, even if the underlying type is Score. Thus, when a Score object is retrieved from the backend through this method, it will be instantiated as a GTLTicTacToeGame object and won’t respond to the outcome property unless you directly access the JSON array.

Asynchronous Nature of API Queries

One important thing to know about the API queries that the generated code executes is that they are all asynchronous. The query is fired off and the method immediately returns. When the API backend processes the request, the completion handler block is called and the result is returned to the client application asynchronously. You need to be careful to not let a user fire off multiple concurrent queries as they will be hogging the API backend and running up your costs to host your API backend on App Engine. The iOS client application handles this by simply disabling the user interface while queries are executing and displaying an activity indicator to the user to indicate that some activity is occurring.