Wednesday, August 4, 2010

Talking with iOS

In this article we will summarize some of the best practices and technologies we have identified to implement a scalable and manageable communication framework to integrate iOS base devices into an existing enterprise application, typically developed using Microsoft technologies.

Selecting the communication protocol


When we need to communicate with an iOS device (or any other mobile client for that matter), one of the first things we need to decide is the protocol to be used during the communication. Although we can use our well tested SOAP over HTTP for this matter, given the limitations of these devices, it’s always better to have something simpler and more efficient. Considering this requirement, the REST (Representational State Transfer) web services become the ideal choice for this matter. In REST, we think in terms of “resources” instead of “actions.” Therefore, rather than defining our own methods, REST leverages the existing methods of an application layer protocol (e.g. HTTP) to manipulate the resources. This avoids the need of having special client side “proxy” classes to perform the communication. For instance, if we want to get a list of users, using a REST service, we will simply perform a HTTP GET request to a pre-defined URI (e.g. http://myserver.com/users) and to update the users we may perform a HTTP POST request where in SOAP based web services, we will invoke web methods with the help of a proxy.

REST has been there for almost 10 years now; and with the Dot.Net 4 framework, developing a REST service has never been easier. Dot.Net 4 WCF has significant improvements for this kind of services compared to its predecessors. One such major improvement is the way it handles the URI mappings. Now we can simply denote our URI mappings using attributes. For more information about Dot.Net 4 improvements, please see here.

On the other hand, iOS SDK has some ready-made facilities for working with common protocols like HTTP. Furthermore, there are few third-party libraries, most notably ASIHTTPRequest, taking this further and provide improved support for HTTP based communication.

Selecting the data format


XML is claimed as the most popular data format which can be used when we need to communicate between heterogeneous systems. However, one significant drawback is its message overhead, the extra payload in addition to the actual data. On the other hand, JSON (Java Script Object Notation) becoming more and more popular due to its efficient and straightforward message structure. As of Dot.Net 4, we have JSON as an alternative data format to XML across the framework. Quite notably, the WCF REST services and WCF Data services supports JSON as an out-of-the box data format. In fact, we can even specify the data format dynamically so our services support both XML and JSON. Despite this strong support, still there are some limitations. However, some third-party libraries like JSON.Net not only fill those gaps but also taking the capabilities to a whole new level. For instance, the JSON.Net library provides a very efficient serialization support, a LINQ to JSON quarry provider, JSON-XML transformer and improved Silverlight and Compact framework support.


Other server side considerations


In an enterprise application, we may have several service contracts and connections with other parts of the system. For instance, we may have a WCF Data service to access the data and number of custom web services implementing the business logic and so on. Furthermore, they may be developed by using different versions of the Dot.Net framework. As a result, we may need to follow different protocols to access these data and functionalities. This kind of issues may negatively affect the communication between constrained environments like an iOS device. One simple way to overcome such issues is to develop a proxy WCF REST service in which we abstract away all those complexities from the iOS devices. This approach not only enables us to reuse our server-side deployment with minimum modifications, but also reduce the complexity of the client-side implementation.

image

Figure: Using WCF REST service as a proxy to reduce the complexity of connectivity.

Client side considerations


Extending ASIHTTPRequest Library
As mentioned in the previous sections, ASIHttpRequest class library provides a rich set of functionalities for using the HTTP protocol including asynchronous requests, web form requests and couple of authentication mechanisms. Extending the base ASIHttpRequest classes allows you to define the common configurations of requests in one place instead of defining them on each time you need to make a request. For instance, you may set the authentication details (e.g. username, password, etc…) and other common http headers (e.g. json as the content type) in this extended class. In this approach, you may only need to set the payload at the time of making a request to the server.

Selecting a JSON framework
As you are using JSON as the data format when communicating with the server, you need to have an efficient way of creating JSON payloads as well as parsing JSON responses you get from the server. Fortunately there are quite a few libraries available out there which provides capabilities around JSON (see http://json.org for a list of libraries). In this document, we are proposing a mechanism where different kinds of processing of the data happen at different levels by using custom helper methods. As such, what we need from a third-party JSON library is the ability to transform a JSON string into an NSArray (in case of collection of data) OR NSDictionary (in case of a single object) and vice-versa. We propose a JSON library called json-framework as it doing this work for us efficiently in iOS platform.





Designing the local data model
As this document is NOT about designing an efficient local data store but implementing an efficient communication platform, we are not going to explore the iOS Core Data framework in detail. Instead, we are going to explore how we can transform an entity data into JSON format and process entity relationships efficiently so that we can synchronize the data with back-end servers with little effort.

In general, when we don’t have circular references (loops) in the data model, we may simply traverse through the object hierarchy recursively and create NSDictionary and NSArray objects based on the type of the objects and their relationships. That is, each object can be represents by using an NSDictionary instance where its properties are entries of the dictionary. Each one-to-one relationship (i.e. the relation referring to a single object) becomes another NSDictionary and each one-to-many relationship becomes an array of such dictionaries (i.e. NSArray whose elements are of type NSDictionary). Then we may simply serialize the top NSDictionary or NSArray by using our selected JSON library to get the JSON representation of our entity instance.

In order to use this method, we must design our data model such that we don’t have circular references. However, in reality it is very difficult to achieve this and most of the time we come across data models with circular references. As such, we may not be able to traverse through the object hierarchy recursively. In this case we may need to manually process the relationships and serialize only the selected ones. In this document, we propose a set of selectors to be defined inside special entity helper classes (see next section for more details) so that we have full control of the serialization process while making the management of the code base relatively easy.

Custom entity helpers
The apps developed for iOS strictly follows the MVC design pattern in which all the heavy processing happens inside view controllers. However, there are many core functionalities we need to use across view controllers and other classes. In this document, we propose extracting those functionalities and define them as separate classes. As this document focuses on communication with external systems, we will only explore one such abstraction we propose in the form of entity helpers. Other forms of abstractions such as Utility classes will be discussed later.

In this document we propose implementing an entity helper class for each entity in your data model. The naming convention we propose is to have the entity name followed by the term “EntityHelper”. For instance, the helper for the entity “Assignment” will be called “AssignmentEntityHelper”. Inside each entity helper, we identify the following key areas of functionalities to be implemented.

1. JSON encoders

2. CoreData helpers

3. Server sync helpers

Please refer to the following header file for details of each type of methods (or selectors).

Please note that the following header definition is just a demonstration only where in a real implementation some of the methods will not be needed while some other methods has to be defined.

image

No comments:

Post a Comment