This is a very basic requirement when you are doing mobile apps to get data from a remote server and then either display or save it for future use. There are two things that we need to accomplish, first make an HTTP request from the app and then parse the JSON response. The HTTP request is done using the NSURLConnection object and the JSON parsing is done with the help of NSJSONSerialization class. In this example we have text field where you can input the country code. When the user taps on submit the button in the navigation bar it goes out to the remote server and gets the response in JSON format. Now you can parse the JSON data to see if the country code was valid or not and if valid then display the detail screen with additional information that was part of the response.
Click here for Backend Java Servlet code
Sample JSON data coming from the remote server
{"success":true,
"countryInfo":{
"code":"BRA",
"name":"Brazil",
"continent":"South America",
"region":"South America",
"lifeExpectancy":62.9,
"gnp":776739.0
}
}
Interface file for Country Object - Country.h
#import <Foundation/Foundation.h>
@interface Country : NSObject
@property (nonatomic, copy) NSString *code;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *continent;
@property (nonatomic, copy) NSString *region;
@property (nonatomic, copy) NSNumber *lifeExpectancy;
@property (nonatomic, copy) NSNumber *gnp;
-(id)initWithNSDictionary:(NSDictionary *)countryInfo_;
@end
Implementation file for Country Object - Country.m
#import "Country.h"
@implementation Country
@synthesize code;
@synthesize name;
@synthesize continent;
@synthesize region;
@synthesize gnp;
@synthesize lifeExpectancy;
-(id)initWithNSDictionary:(NSDictionary *)countryInfo_
{
self = [super init];
if (self) {
NSDictionary *countryInfo = countryInfo_;
NSLog(@"Country Info = %@",countryInfo);
self.code = [countryInfo valueForKey:@"code"];
self.name = [countryInfo valueForKey:@"name"];
self.continent = [countryInfo valueForKey:@"continent"];
self.region = [countryInfo valueForKey:@"region"];
self.gnp = [countryInfo valueForKey:@"gnp"];
self.lifeExpectancy = [countryInfo valueForKey:@"lifeExpectancy"];
}
return self;
}
- (void)dealloc
{
self.code = nil;
self.name = nil;
self.continent = nil;
self.region = nil;
self.gnp = nil;
self.lifeExpectancy = nil;
}
@end
Interface file for App Delegate - HttpRequestJSONAppDelegate.h
#import <UIKit/UIKit.h>
#import "InputViewController.h"
@interface HttpRequestJSONAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navigationController;
@property (strong, nonatomic) InputViewController *inputViewController;
@end
Implementation file for App Delegate - HttpRequestJSONAppDelegate.m
#import "HttpRequestJSONAppDelegate.h"
@implementation HttpRequestJSONAppDelegate
@synthesize navigationController;
@synthesize inputViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//create the navigation controller and add the controllers view to the window
navigationController = [[UINavigationController alloc] init];
[self.window addSubview:[self.navigationController view]];
//check if the Input viewcontroller eixsts, otherwise create it
if(self.inputViewController == nil)
{
InputViewController *inputView = [[InputViewController alloc] init];
self.inputViewController = inputView;
}
//push the first viewcontroller into the navigation view controller stack
[self.navigationController pushViewController:self.inputViewController animated:YES];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
//do nothing
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
//do nothing
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
//do nothing
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
//do nothing
}
- (void)applicationWillTerminate:(UIApplication *)application {
//do nothing
}
@end
Interface file for Root View Controller - InputViewController.h
#import <UIKit/UIKit.h>
#import "DisplayViewController.h"
@interface InputViewController : UIViewController
@property (nonatomic, strong) UILabel *myLabel;
@property (nonatomic, strong) UILabel *myHelpText;
@property (nonatomic, strong) UITextField *countryCode;
@property (strong, nonatomic) DisplayViewController *displayViewController;
@end
Implementation file for Root View Controller - InputViewController.m
#import "InputViewController.h"
@interface InputViewController ()
@end
@implementation InputViewController
@synthesize myLabel;
@synthesize countryCode;
@synthesize displayViewController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//set the title of the navigation view
[self.navigationItem setTitle:@"Country Inquiry"];
//create a text field for our country code and add to the view
countryCode = [[UITextField alloc] init];
[countryCode setBorderStyle: UITextBorderStyleRoundedRect];
[countryCode setFrame:CGRectMake(10.0f,10.0f,200.0f,30.0f)];
[countryCode setPlaceholder:@"Enter Country Code here"];
[countryCode setContentVerticalAlignment: UIControlContentVerticalAlignmentBottom];
[countryCode setAutocapitalizationType: UITextAutocapitalizationTypeAllCharacters];
[self.view addSubview: countryCode];
//create a label to display error message
CGRect myFrame = CGRectMake(10.0f, 50.0f, 250.0f, 40.0f);
self.myLabel = [[UILabel alloc] initWithFrame:myFrame];
self.myLabel.font = [UIFont boldSystemFontOfSize:16.0f];
self.myLabel.textAlignment = NSTextAlignmentLeft;
[self.view addSubview:self.myLabel];
//some help text for users
myFrame.origin.y += 30.0f;
myFrame.size.height += 100.0f;
self.myHelpText = [[UILabel alloc] initWithFrame:myFrame];
self.myHelpText.numberOfLines = 0;
self.myHelpText.text = @"Some of the valid Country codes are USA, CHN, CAN and BR";
[self.view addSubview:self.myHelpText];
//create a submit button in the navigation bar
UIBarButtonItem *myButton = [[UIBarButtonItem alloc]
initWithTitle:@"Submit"
style:UIBarButtonItemStylePlain
target:self
action:@selector(getCountryInfo:)];
[self.navigationItem setRightBarButtonItem:myButton];
}
- (void) getCountryInfo:(id)sender {
//get reference to the button that requested the action
UIBarButtonItem *myButton = (UIBarButtonItem *)sender;
//check which button it is, if you have more than one button on the screen
//you must check before taking necessary action
if([myButton.title isEqualToString:@"Submit"]){
NSLog(@"Clicked on the bar button");
self.myLabel.text = @"";
//string for the URL request
NSString *myUrlString = @"http://demo.mysamplecode.com/JQuery/CountryInfo";
//create string for parameters that we need to send in the HTTP POST body
NSString *body = [NSString stringWithFormat:@"countryCode=%@", countryCode.text];
//create a NSURL object from the string data
NSURL *myUrl = [NSURL URLWithString:myUrlString];
//create a mutable HTTP request
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:myUrl];
//sets the receiver’s timeout interval, in seconds
[urlRequest setTimeoutInterval:30.0f];
//sets the receiver’s HTTP request method
[urlRequest setHTTPMethod:@"POST"];
//sets the request body of the receiver to the specified data.
[urlRequest setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
//allocate a new operation queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//Loads the data for a URL request and executes a handler block on an
//operation queue when the request completes or fails.
[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 && error == nil){
//process the JSON response
//use the main queue so that we can interact with the screen
dispatch_async(dispatch_get_main_queue(), ^{
[self parseResponse:data];
});
}
else if ([data length] == 0 && error == nil){
NSLog(@"Empty Response, not sure why?");
}
else if (error != nil){
NSLog(@"Not again, what is the error = %@", error);
}
}];
}
}
- (void) parseResponse:(NSData *) data {
NSString *myData = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"JSON data = %@", myData);
NSError *error = nil;
//parsing the JSON response
id jsonObject = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingAllowFragments
error:&error];
if (jsonObject != nil && error == nil){
NSLog(@"Successfully deserialized...");
//check if the country code was valid
NSNumber *success = [jsonObject objectForKey:@"success"];
if([success boolValue] == YES){
//if the second view controller doesn't exists create it
if(self.displayViewController == nil){
DisplayViewController *displayView = [[DisplayViewController alloc] init];
self.displayViewController = displayView;
}
//set the country object of the second view controller
[self.displayViewController setJsonObject:[jsonObject objectForKey:@"countryInfo"]];
//tell the navigation controller to push a new view into the stack
[self.navigationController pushViewController:self.displayViewController animated:YES];
}
else {
self.myLabel.text = @"Country Code is Invalid...";
}
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
Interface file for Detail View Controller - DisplayViewController.h
#import <UIKit/UIKit.h>
@interface DisplayViewController : UIViewController
@property (nonatomic, strong) id jsonObject;
@property (nonatomic, strong) UILabel *countryCode;
@property (nonatomic, strong) UILabel *name;
@property (nonatomic, strong) UILabel *continent;
@property (nonatomic, strong) UILabel *region;
@property (nonatomic, strong) UILabel *lifeExpectancy;
@property (nonatomic, strong) UILabel *gnp;
@end
Implementation file for Detail View Controller - DisplayViewController.m
#import "DisplayViewController.h"
#import "Country.h"
@interface DisplayViewController ()
@end
@implementation DisplayViewController
@synthesize jsonObject;
@synthesize countryCode;
@synthesize name;
@synthesize continent;
@synthesize region;
@synthesize lifeExpectancy;
@synthesize gnp;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//set the title of the navigation view
[self.navigationItem setTitle:@"Country Detail"];
//bunch of labels for country information
CGRect myFrame = CGRectMake(10.0f, 10.0f, 250.0f, 30.0f);
self.countryCode = [[UILabel alloc] initWithFrame:myFrame];
self.countryCode.font = [UIFont boldSystemFontOfSize:20.0f];
[self.view addSubview:self.countryCode];
myFrame.origin.y += 25.0f;
self.name = [[UILabel alloc] initWithFrame:myFrame];
[self.view addSubview:self.name];
myFrame.origin.y += 25.0f;
self.continent = [[UILabel alloc] initWithFrame:myFrame];
[self.view addSubview:self.continent];
myFrame.origin.y += 25.0f;
self.region = [[UILabel alloc] initWithFrame:myFrame];
[self.view addSubview:self.region];
myFrame.origin.y += 25.0f;
self.lifeExpectancy = [[UILabel alloc] initWithFrame:myFrame];
[self.view addSubview:self.lifeExpectancy];
myFrame.origin.y += 25.0f;
self.gnp = [[UILabel alloc] initWithFrame:myFrame];
[self.view addSubview:self.gnp];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
//create country object from dictionary data
Country *country = [[Country alloc] initWithNSDictionary:jsonObject];
//format decimal data
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:2];
//set the label values from the country object
self.countryCode.text = [[NSString alloc] initWithFormat:@"Country Code = %@", country.code ];
self.name.text = [NSString stringWithFormat:@"Name = %@", country.name] ;
self.continent.text = [NSString stringWithFormat:@"Continent = %@", country.continent] ;
self.region.text = [NSString stringWithFormat:@"Region = %@", country.region] ;
self.lifeExpectancy.text = [NSString stringWithFormat:@"Life Expenctancy = %@",
[formatter stringFromNumber:country.lifeExpectancy]];
self.gnp.text = [NSString stringWithFormat:@"GNP = %@",
[formatter stringFromNumber:country.gnp]] ;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
No comments:
Post a Comment
NO JUNK, Please try to keep this clean and related to the topic at hand.
Comments are for users to ask questions, collaborate or improve on existing.