How to sync data in iOS

Sync data in iOS Development using Objective-C JSON and REST

Syncing data in iOS can be pretty intimidating if you’re new to native iOS development, but fear not! iOS’ Foundation framework gives you just what you need to perform RESTful web services between your app and a remote web server. In other words, to sync data in iOS, all you’ll need is Objective-C to follow the REST architecture style. The examples are shown using synchronized transmission of data in JSON format rather than asynchronous. Though I will only discuss asynchronous and briefly about the server-side at the end.

Super short REST Overview

REST is a type of transmission architecture. REST enables apps to communicate using HTTP or HTTPS. The latter is secured. HTTP has more than four methods (or verbs) that are used to indicate a desired action. The most commonly used methods are POST, GET, PUT and DELETE.

POST

POST is the HTTP method to use when sending data from the app to the server. Before we send data to the server, the data must be parsed as JSON. If your data are in a local database, use Core Data to retrieve them and place them in an NSDictionary or NSArray form.


/* Allocate and initialize a capacity */
NSMutableDictionary *sendAsJSON = [[NSMutableDictionary alloc] 
                                    initWithCapacity:1]

/* Set a message as the object */
[sendAsJSON setObject:@"Hi Server" 
            forKey:"@msgToServer"];

/* Parse the NSMutableDictionary to 
   be sent to the server by
   using NSJSONSerialization
   and save as NSData */
NSData *message = [NSJSONSerialization dataWithJSONObject: sendAsJSON 
                                       options:0 
                                       error:nil];

/* Create NSURL to declare the HTTP path */
NSURL *apiURL = [NSURL URLWithString:@"http://api/post/"];

/* Make a request object */
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: apiURL];

/* Declare the HTTP verb or method */
[request setHTTPMethod:@"POST"];

/* Indicate in the HTTP body the 
   data to be pushed to server */
[request setHTTPBody:message];

NSURLResponse *serverResponse; // just a response to use in NSURLConnection
NSError *e;
/* Send the data to the server via
   synchronous transmission */
[NSURLConnection sendSynchronousRequest:request 
                 returningResponse:&serverResponse 
                 error:&e];

In the above code, an NSMutableDictionary is allocated and initalized with a capacity of 1. Afterwards, we add a simple string object with a key. These will be sent to the server.

To send the NSMutableDictionary to the server, we use NSJSONSerialization to parse the data and save into an NSData variable called message.

The next lines of code are necessary to create an HTTP POST request. First we enter the url of the server where the post request will go. Afterwards, we make a request object using NSMutableURLRequest. Having a request object enables us to set the HTTP method as POST and set the HTTP body to the variable message.

NSURLConnnection is responsible for sending the request object to the server.

The server should get a JSON object looking like this:


{ 
   "msgToServer": "Hi Server"
}

GET

GET is the HTTP method to get response data from the server.


NSError *error;
NSURL *apiURL = [NSURL URLWithString:@"http://api/get/"];

/* Declare the HTTP Verb or method */
[request setHTTPMethod:@"GET"];

NSURLResponse *urlResponse = nil;

/* Make a GET request to the remote server */
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: apiURL];

NSData *serverMessage = [NSURLConnection sendSynchronousRequest:request 
                                         returningResponse:&urlResponse 
                                         error:&e];

/* Use NSJSONSerialization to parse 
   the NSData that was just retrieved 
   from the server */
NSMutableArray *responseData = [NSJSONSerialization JSONObjectWithData:serverMessage 
                  options:kNilOptions 
                  error:&error];

Just like POST, we set the HTTP method as GET and set the url path to the server where we’ll get data. We also make a request object, but unlike POST, we’re not sending data to server. We want to get data from the server, so there’s no need to set the HTTP body. In other cases, you might want to add parameters and query strings in the URL. The data from the server should now be available in responseData. You can use the contents of responseData in your app. Note that you might not get your data in JSON format all the time. Depending on how the web services on the server side are configured, the response data might be in XML or CSV format, so really, responseData doesn’t have to be an NSArray like the example above.

PUT

The idea is the same as POST but you should use it to make updates. Let’s say you have an entry in the server database with an id of 1 and a message of “Dogs are awesome.” And, you want to update the message to “I have blueberries.” You can add the id and message in the url as query strings.


/* Save url path into a variable so that 
   we can append parameters */
NSString *urlString = @"http://api/put/";
/* Append the parameters */
urlString = [urlString stringByAppendingString:@"?id=1"];
urlString = [urlString stringByAppendingString:@"&message=\"I have bluerries\""];

/* Enter the path to NSURL */
NSURL *urlForPUT = [NSURL URlWithString:urlString];

[request setHTTPMethod:@"PUT"];

/* Must include for PUT to work */
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

/*Then do the synchronous request */
[NSURLConnection sendSynchronousRequest:request 
                 returningResponse:&urlResponse 
                 error:&e];

To properly make a query string, we don’t directly enter the path of the url in NSURL. We make a seperate NSString instance variable for the url and append the query strings afterwards. This is more proper than directly entering the URL path with the query strings like we did with the POST and GET examples. This way, the query string values can be dynamic. For example, the id won’t always be 1. So, to set it dynamically we can do this:


urlString = [urlString stringByAppendingString:[NSString stringWithFormat:@"?id=%d", theIdVariable]];

DELETE

Delete is the same idea as PUT. You can have a query string in the URL. In PUT, you usually just need one unique property like an id to indicate which entry in the server database you want to delete.


NSString *urlString = @"http://api/delete/";
urlString = [urlString stringByAppendingString:@"?id=1"];

NSURL *urlForDEL = [NSURL URlWithString:urlString];

[request setHTTPMethod:@"DELETE"];

[NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&e];

Aysnchronous

There’s not really much of a big difference in code if you choose to use asynchronous requests. You’ll still indicate the HTTP method, set the URL, be able to use HTTP body,and have to parse your data before sending to or receiving from the server. Everything is generally the same, except that you’ll be sending your request as asynchronous. And, NSURLConnection class has got you covered.


[NSURLConnection sendAsynchronousRequest:apiURL
                 queue:[NSOperationQueue mainQueue]
                 completionHandler:^(NSURLResponse *response, NSData *data, NSError *e) {
   /* This is handler function when request has completed */
   NSLog(@"Async completed.");
   NSLog(@"NSData: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];

To perform asynchronous transmission, use sendAsynchronousRequest: queue: completionHandler instead of sendSynchronousRequest: returningResponse: error. The former’s completionHandler takes in an anonymous function that can help inform your app as to whether the async transmission has finished successfully or with errors. You can also use it to perform tasks once the transmission has finished. The queue takes an NSOperationQueue so that your app can run smoothly (complying to async performance).

What about the server-side?

While this article is mainly about how to sync data in iOS, it would be incomplete if I didn’t talk a little bit about the server-side. After all, it’s necessary when syncing data. The server must have API’s that can send responses and receive HTTP requests. If not, then you have to make sure there’s an API or your data won’t really be doing anything in the server.

Conclusion

I used synchronous on the examples here primarily because it’s easier to explain than asynchronous. Asynchronous can be tricky if you’re new to these types of transmissions. As long as you understand the difference between sync and async, the asynchronous part of NSURLConnection is all you need to know in order to make your app asynchronize to the server. In other words, if you understand async then you’ll understand what sendAsynchronousRequest: queue: completionHandler in NSURLConnection are used for. To sum it up, the examples above depict the basic ideas to sync data in iOS using Objective-C and the REST architecture.

*Feel free to post any questions or points that you would like me to answer or expand upon in the comments section.