Tuesday 5 March 2013

Dynamically Controlling Your Application From The Web


Often times you find yourself in a situation where you might want to control yourapplication remotely. You may want to enable / disable features at A Certain time, push messages to all of your users, or do some cross promotion whenever you launch a new application. All of this can easily be done with a little JSON and some simple web interface coding .
 
In this tutorial, I will show you how to use ASIHTTPRequest alongwith JSONKIT to fetch, parse and interpret remote JSON that will ultimately change how our application behaves. For this example, we are going to make a simple "nos" popup that will nag the user to download your latest application. When you set a remote flag to true, all users will see the popup every time they launch the application. The popup will also display a dynamic message from the web and link to a location specified in the JSON.

First The JSON

First, let's chat a little bit about the JSON we will be using. Here's what it will look like:
{
    "Nos": true,
    "Message": "Check out Smart Lockscreen Creator!"
    "Url": "http://itunes.apple.com/us/app/smart-lockscreen-creator/id419890996?mt=8"
}
The field names should be pretty self explanatory. We will use JSON kit to parse these fields into to NSDictionary.

Second The Libraries

As mentioned before, we will be using 2 libraries to get the job done.
  • ASIHTTPRequest ASIHTTPRequest is. to easy to use wrapper around the CFNetwork API that makes some of the more tedious aspects of communicating with web servers easier
  • JSONKit - A JSON parser written in C with an Objective-C wrapper.
Make sure you download their source and follow each of their instructions for setting up your project to use them. JSONKit is pretty much drag in the source and you are good to go. ASI has a few dependancies framework that you are going to have to work out. The instructions for setting it up are here .

3rd The Code - Download And Parse

You can add the code to fetch and control your application wherever you see fit, however I have added mine to the application's delegate method.
    / / 1 Fetch out to the web 
    NSURL  * url =  [ NSURL URLWithString : @ "http://f.cl.ly/items/2y141v3O0G2e2Y2W3P24/alert.json" ] ;
    ASIHTTPRequest * request =  [ ASIHTTPRequest requestWithURL : url ] ;
 
    / / 2 Completion block 
    [ request setCompletionBlock : ^ ( void )  { 
        NSString  * string response =  [ request responseString ] ;
         / / 3 parse the response 
        NSDictionary  * responseDict =  [ responseString objectFromJSONString ] ;
 
        / / 4 pull out data 
        BOOL nos =  [ [ responseDict objectForKey : @ "nag" ] boolValue ] ;
         NSString  * message =  [ responseDict objectForKey : @ "message" ] ;
        self.nagURL =  [ NSURL URLWithString : [ responseDict objectForKey : @ "url" ] ] ;
 
        / / 5 If NOS is true, then show the alert 
        if ( nos )  { 
            UIAlertView * alert =  [ [ [ UIAlertView alloc ] initWithTitle : @ "Message"  
                                                             message : message
                                                            delegate : self
                                                   cancelButtonTitle : @ "Cancel"  
                                                   button other titles : @ "Go" , nil ] autorelease ] ;
             [ alert show ] ;
         } 
    } ] ,
     / / 6 Start the request 
    [ request startAsynchronous ] ;
In # 1, we fetch out to the web and pull down the json string that contains our configuration settings. # 2 sets the completion block for the request. If you are unfamiliar with this pattern, the request fires off into a new thread and the block gets executed AFTER the request completes. That way, we can keep all of our code in line rather than messing around with target and selector callbacks .
For # 3, we are using JSONKit's category on NSString that returns an NSDictionary representation of the JSON string It could not be easier.
Line # 4 is where we extract the info from the dictionary and assign it to local variables. We set the global property nagURL here as well. The reason we must create a property for nagURL is we need to use it again in the delegate method for the UIAlertView in order to send the user to the specified url from the web.
Line # 5 is where we check if nos is true and then show the alert. Make sure to set the delegate to our calling class Sun that we can respond accordingly.
Finally, in # 6, we start the request asynchronously.
The last thing to do is implement the delegate method for the alert view. It's pretty straight forward:
-  ( void ) alert view : ( UIAlertView * ) alert view didDismissWithButtonIndex : ( NSInteger ) index button { 
    if ( button index ==  1 )  { 
        [ [ UIApplication sharedApplication ] openURL : self.nagURL ] ;
     } 
}
We simply check to see if the user pressed the "Go" button if so, we send them to the URL specified by the nagURL property.

Conclusion

And there you have it. A very simple example of how you can control some portion of your applicaiton's functionality based on remote web data. You could expand upon this in a number of ways including:
  • Enabling / disabling parts of the app
  • Loading "news" in some sort of ticker
  • Daily promotions
  • Promote new apps
  • Daily content (jokes, words, inspiration, scripture, etc ...)
If you have any questions or comments, you can leave the here or write me on Twitter.
The source project for this post is available here .

No comments:

Post a Comment