Code_Snippet

Thursday Tech Tip – Sending HTTP Posts in iOS

I came across a challenge the other day at work while trying to include a click event into an iOS app. Essentially, when a user clicks on an object within the app that involves a segue sequence, such as an article in an RSS reader app, we want to record that click by logging it in an app on a remote server. I tried to use some of my company’s existing JavaScript functions that make API calls to our remote observation server. The JavaScript approach fails even if you include the call in your Main implementation file to:

#import <JavaScriptCore/JavaScriptCore.h>

The failure, at least in our case, was due to the fact that all of our JavaScript doesn’t kick off until we get the page.load or window.ready response from the browser. If your code only includes methods for making the call and is not browser dependent, you just might be ok. Regardless, I tried to come up with a better way for handling REST calls in iOS then depending on JS. So, I pieced together what I could find into the following native Objective C approach below.

Below is an example of an HTTP Post Implementation in a generic iOS RSS Reader App. Essentially what I have done is append the URL of the article being clicked to a bit.ly API call which should return the shortened version of the URL which I can then use however. You could essentially use the approach below for most modern REST API calls. I though I would share this so some of you won’t have to bang your head for a while like I did. Even better, you could write an HTTP_Post.h and HTTP_Post.m files for use in multiple projects. You would just pass in the ‘xhrUrl’ and ‘postBody’ as variables and request back the response in your project code. You can check out and fork the sample project I posted on GitHub.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"showDetail"]) {

        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSString *linkUrl = [feeds[indexPath.row] objectForKey: @"link"];
        NSString *xhrUrl = [NSString stringWithFormat:@"%@%@", @"https://api-ssl.bitly.com/v3/user/link_save?access_token=ACCESS_TOKEN&amp;longUrl=",linkUrl];

        //prepare request
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setURL:[NSURL URLWithString:xhrUrl]];
        [request setHTTPMethod:@"POST"];

        //set headers
        NSString *contentType = [NSString stringWithFormat:@"text/xml"];
        [request addValue:contentType forHTTPHeaderField: @"Content-Type"];

        //create the body
        NSMutableData *postBody = [NSMutableData data];
        [postBody appendData:[[NSString stringWithFormat:@""] dataUsingEncoding:NSUTF8StringEncoding]];
        [postBody appendData:[[NSString stringWithFormat:@"<data></data>"] dataUsingEncoding:NSUTF8StringEncoding]];
        [postBody appendData:[[NSString stringWithFormat:@""] dataUsingEncoding:NSUTF8StringEncoding]];

        //post
        [request setHTTPBody:postBody];

        //get response
        NSHTTPURLResponse* urlResponse = nil;
        NSError *error = [[NSError alloc] init];
        NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&amp;urlResponse error:&amp;error];
        NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
        NSLog(@"Response Code: %d", [urlResponse statusCode]);
        if ([urlResponse statusCode] &gt;= 200 &amp;&amp; [urlResponse statusCode] &lt; 300) {
            NSLog(@"Response: %@", result);

        //here you get the response

        }

        //open article
        [[segue destinationViewController] setUrl:linkUrl];
    }
}

 

Leave a Reply