iOS Sample Code

Platform: Apple

Source Code : Github Exit


iOS sample code which uses the Envirofacts RadNet Representational State Transfer (REST) Application Programming Interface (API).

Overview

This sample will provide the steps to create a simple iOS application that can consume Radiation (RadNet) Data. The Envirofacts RadNet database contains sample results for a variety of radionuclides and radiation types from 200 monitoring stations across all 50 states and the American Territories. This API Data Sample, queries and displays results of these samples, for an entered analyte. Following these steps in order will allow the application to recreate the sample project.

Requirements

This solution was built using:

  • Mac OSX Lion
  • xCode 4.2

Assumptions:

  • xCode is already installed on a working version of Mac OSX.

For this sample, create an application that takes a radioactive element name and queries the Web service. The Web service returns result amount, Combined Standard Uncertainty (CSU), Minimum Detectable Concentrations (MDC), result unit, and result date. The application will allow scrolling through the results 10 at a time.

Top of Page

Create a New Project

For this sample, create an iOS project that will consume and list result data for an analyte from the Envirofacts Radiation (RadNet) Web service.

Create a new xCode Project by opening xCode, clicking on “File”, then “New”, and then “New Project”.

iOS create a new project

Select “Single View Application”.

iOS application setup

Name the project. For this it is named SampleEpa. Select Device Family “iPhone”, check “User Storyboard”, and click “Next”. Save the files anywhere.

iOS naming project

On the iOS Application Target change the Identifier to gov.epa.sample.dfe.SampleEPA where SampleEPA is the project name.

In the Navigator Pane select “MainStoryboard.storyboard” and then in the View Controller Scene “Expand View Controller”.

iOS storyboard

From the Object Library Pane drag and place the following objects on to the view.

  1. Label – double click on the label and Type “Analyte ID”
  2. Text Field
  3. Round Rectangular Button- double click on the button and Type “Query”
  4. Table View
  5. Toolbar

On the tool bar, drag:

  • Bar Button Item – double click on the button and Type “Prev”
  • Flexible Space Bar Button Item
  • Bar Button Item – double click on the button and Type “Next”

iOS create toolbar with buttons

Click on the Show Assistant Editor (button on the right top part of xcode that looks like a bow tie and shirt) . Make sure on the right side of the split pane the ViewController.h file is selected. Press the Control button and drag the following items to the @end statement in the VIewController.h file.

  1. Text Field -when prompted name it “AnalyteField”
  2. Query Button -when prompted name it “QueryButton”
  3. Table View -when prompted name it “resultTableView”
  4. Toolbar -when prompted name it “ToolBar”
  • Prev Button -when prompted name it “Prev”
  • Next Button -when prompted name it “Next”

iOS Show Assistant Editor

Now that the Project and the Interface are set up, finish the development.
In xCode select the Show the Standard editor button in the upper right corner.
In the Navigator pane right click on the “SampleEPA (project name)” folder, then “New File”, and
then select “Objective-C” class. Name the class AppResultsData and add the following attributes:

//// AppResultsData.h// SampleEPA12

//

// Created by Kevin Dunn on 3/9/12.

// Copyright (c) 2012 __MyCompanyName__. All rights reserved.

//

#import <Foundation/Foundation.h>@interface AppResultsData : NSObject

{

NSString *ANA_NUM;

NSString *RESULT_ID;

NSString *ANALYTE_ID;

NSString *RESULT_AMOUNT;

NSString *CSU;

NSString *MDC;

NSString *RESULT_UNIT;

NSString *RESULT_DATE;

NSString *RESULT_IN_SI;

NSString *CSU_IN_SI;

NSString *MDC_IN_SI;

NSString *SI_UNIT;

}

@property (nonatomic, retain) NSString *ANA_NUM;

@property (nonatomic, retain) NSString *RESULT_ID;

@property (nonatomic, retain) NSString *ANALYTE_ID;

@property (nonatomic, retain) NSString *RESULT_AMOUNT;

@property (nonatomic, retain) NSString *CSU;

@property (nonatomic, retain) NSString *MDC;

@property (nonatomic, retain) NSString *RESULT_UNIT;

@property (nonatomic, retain) NSString *RESULT_DATE;

@property (nonatomic, retain) NSString *RESULT_IN_SI;

@property (nonatomic, retain) NSString *CSU_IN_SI;

@property (nonatomic, retain) NSString *MDC_IN_SI;

@property (nonatomic, retain) NSString *SI_UNIT;

@end

In the implementation class synthesize the attributes and then dealloc them as follows.

//// AppResultsData.m// SampleEPA12

//

// Created by Kevin Dunn on 3/9/12.

// Copyright (c) 2012 __MyCompanyName__. All rights reserved.

//#import "AppResultsData.h"

@implementation AppResultsData

@synthesize ANA_NUM,RESULT_ID,ANALYTE_ID,RESULT_AMOUNT,

CSU,MDC,RESULT_UNIT,RESULT_DATE,RESULT_IN_SI,

CSU_IN_SI,MDC_IN_SI,SI_UNIT;

-(id) init{

[super init];

return self;

}

-(void) dealloc

{

[self setANA_NUM:nil];

[self setRESULT_ID:nil];

[self setANALYTE_ID:nil];

[self setRESULT_AMOUNT:nil];

[self setCSU:nil];

[self setMDC:nil];

[self setRESULT_UNIT:nil];

[self setRESULT_DATE:nil];

[self setRESULT_IN_SI:nil];

[self setCSU_IN_SI:nil];

[self setMDC_IN_SI:nil];

[self setSI_UNIT:nil];

}

@end

From the Navigator pane, select “ViewController.h” and add the following:

  1. UITableViewDataSource and NSXMLParserDelegate to the interface declaration
  2. soapResults, Page, ItemsPerPage, appResultsData, dataSet, and dataset attributed
  3. buildURL methods
  4. Initializations to the {} block.
//// ViewController.h// SampleEPA12

//

// Created by Kevin Dunn on 2/8/12.

// Copyright (c) 2012 __MyCompanyName__. All rights reserved.

//#import <UIKit/UIKit.h>

#import "AppResultsData.h"

@interface ViewController : UIViewController <NSXMLParserDelegate, UITableViewDataSource>

{

NSMutableData *webData;

NSMutableString *soapResults;

NSURLConnection *conn;

//---xml parsing---

NSXMLParser *xmlParser;

NSMutableArray *dataSet;

AppResultsData *appResultsData;

UITableView *resultsTableView;

UIToolbar *ToolBar;

int Page;

int ItemsPerPage;

}

@property (retain, nonatomic) IBOutlet UITableView *resultTableView;

@property (retain, nonatomic) IBOutlet UITextField *AnalyteField;

@property (retain, nonatomic) IBOutlet UIButton *QueryButton;

@property (retain, nonatomic) IBOutlet NSMutableString *soapResults;

@property (retain, nonatomic) IBOutlet UIToolbar *ToolBar;

@property (retain, nonatomic) IBOutlet UIBarButtonItem *Prev;

@property (retain, nonatomic) IBOutlet UIBarButtonItem *Next;

@property ( nonatomic) int Page;

@property ( nonatomic) int ItemsPerPage;

@property (strong, nonatomic) AppResultsData *appResultsData;

@property (nonatomic, retain) NSMutableArray *dataSet;

-(NSString *)buildURL:(NSString *)analyte;

@end

In the ViewController implementation class synthesize the following:

@implementation ViewController

@synthesize AnalyteField;

@synthesize QueryButton;

@synthesize resultTableView;

@synthesize soapResults;

@synthesize appResultsData;

@synthesize dataSet;

@synthesize ToolBar;

@synthesize Prev;

@synthesize Next;

@synthesize Page;

@synthesize ItemsPerPage;

When the ViewController is loaded, the viewDidLoad method is called (this should have been auto generated). Add the following to the viewDidLoad method:

- (void)viewDidLoad{[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

[QueryButton addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];

//UIToolbar *toolBar = [[UIToolbar alloc] init];

ToolBar.hidden=true;

[self setPage:1];

[self setItemsPerPage:10];

}

When the buttons are pressed from the user interface, methods need to be called so they can control what happens when they are pressed. Create the following methods:

- (IBAction)nextAction:(id)sender {NSString *analytId = AnalyteField.text;[self setPage: Page+1];

Prev.enabled=true;

NSString *url=[self buildURL:analytId];

[self getWebDataFromURL:url];

//[AnalyteField resignFirstResponder];
}

- (IBAction)prevAction:(id)sender {

NSString *analytId = AnalyteField.text;

if(Page<=2){

Prev.enabled=false;

[self setPage: 1];

}else{

[self setPage: Page-1];

}

NSString *url=[self buildURL:analytId];

[self getWebDataFromURL:url];

// [AnalyteField resignFirstResponder];

}

-(void)buttonAction{

NSString *analytId = AnalyteField.text;

NSString *url=[self buildURL:analytId];

[self getWebDataFromURL:url];

[AnalyteField resignFirstResponder];

Prev.enabled=false;

}

 

Top of Page

Implement the Data Request

In order to make a service call to the EPA, RadNet RESTful Service includes the following method
declaration in the ViewController Implementation class. More details on what can be passed to the
service can be found here: http://iaspub.epa.gov/enviro/erams_query_v2.simple_query

/*URL builder to epa site*/-(NSString *)buildURL:(NSString *)analyteId{int startRow = (Page-1)*ItemsPerPage +1;

int endRow = Page*ItemsPerPage;

NSString *urlTemp = @"http://iaspub.epa.gov/enviro/efservice/ERM_RESULT/ANALYTE_ID/";

urlTemp =[urlTemp stringByAppendingString:analyteId];

urlTemp =[urlTemp stringByAppendingString:@"/rows/"];

urlTemp =[urlTemp stringByAppendingString:[NSString stringWithFormat:@"%d", startRow]];

urlTemp =[urlTemp stringByAppendingString:@":"];

urlTemp =[urlTemp stringByAppendingString:[NSString stringWithFormat:@"%d", endRow]];

NSLog(urlTemp);

return urlTemp;

}

-(void) getWebDataFromURL:(NSString *)urlString{

NSString *queryString =[NSString stringWithFormat: urlString];

NSURL *url = [NSURL URLWithString:queryString];

NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];

[req addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

[req addValue:0 forHTTPHeaderField:@"Content-Length"];

[req setHTTPMethod:@"GET"];

// [activityIndicator startAnimating];

conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];

if (conn) {

webData = [[NSMutableData data] retain];

dataSet = [[NSMutableArray alloc] init];

}

}

In order to handle the connection to the Web service the following call back methods need to be implemented.

/*Connection Code*/-(void) connectionDidFinishLoading:(NSURLConnection *) connection {NSLog(@"DONE. Received Bytes: %d", [webData length]);

if([webData length]>0){

if (xmlParser)

{

[xmlParser release];

}

xmlParser = [[NSXMLParser alloc] initWithData: webData];

[xmlParser setDelegate: self];

[xmlParser setShouldResolveExternalEntities:YES];

[xmlParser parse];

// Tell the UITableView to reload the data

[self.resultTableView reloadData];

//Tool Bar for Next 5

ToolBar.hidden=false;

}

// Connection resources release.

[connection release];

[webData release];

}

-(void) connection:(NSURLConnection *) connection

didReceiveResponse:(NSURLResponse *) response {

[webData setLength: 0];

}-(void) connection:(NSURLConnection *) connection

didReceiveData:(NSData *) data {

[webData appendData:data];

}

-(void) connection:(NSURLConnection *) connection

didFailWithError:(NSError *) error {

[webData release];

[connection release];

}

The NSXMLParser requires some call back methods as well.

/*Parser Code*/-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName

namespaceURI:(NSString *) namespaceURI

qualifiedName:(NSString *) qName

attributes:(NSDictionary *) attributeDict

{

if( [elementName isEqualToString:@"ERM_RESULT"])

{

appResultsData = [[AppResultsData alloc] init];

}

//new tag new results

[soapResults setString:@""];

}-(void)parser:(NSXMLParser *)parser didEndElement:

(NSString *)elementName

namespaceURI:(NSString *)namespaceURI

qualifiedName:(NSString *)qName

{

if ([elementName isEqualToString:@"ERM_RESULT"])

{

[dataSet addObject:appResultsData];

[soapResults setString:@""];

[appResultsData release];

}

if ([elementName isEqualToString:@"ANA_NUM"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setANA_NUM:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"RESULT_ID"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setRESULT_ID:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"ANALYTE_ID"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setANALYTE_ID:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"RESULT_AMOUNT"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setRESULT_AMOUNT:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"CSU"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setCSU:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"MDC"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setMDC:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"RESULT_UNIT"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setRESULT_UNIT:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"RESULT_DATE"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setRESULT_DATE:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"RESULT_IN_SI"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setRESULT_IN_SI:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"CSU_IN_SI"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setCSU_IN_SI:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"MDC_IN_SI"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setMDC_IN_SI:tmpstr];

[soapResults setString:@""];

}

if ([elementName isEqualToString:@"SI_UNIT"])

{

NSString *tmpstr = [[NSString alloc] init];

tmpstr = [tmpstr stringByAppendingString:soapResults];

[appResultsData setCSU_IN_SI:tmpstr];

[soapResults setString:@""];

}

}

-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string

{

if (!soapResults) {

// soapResults is an NSMutableString instance variable

soapResults = [[NSMutableString alloc] init];

}

if([string length] > 0){

NSString *cleanString = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

if([cleanString length] >0){

[soapResults appendString: string];

}

}

}

The ViewController also handles the Table View methods. The following methods need to be added to the ViewController implementation class:

/*Table View Methods*/#pragma mark - Table View Data Source Methods- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

//NSLog(@"%s", __FUNCTION__);

NSLog(@"self.dataSet count: %d", [self.dataSet count]);

return [self.dataSet count];

}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"cellForRow called");

static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:

SimpleTableIdentifier];

// UITableViewCell cell needs creating for this UITableView row.

if (cell == nil)

{

cell = [[[UITableViewCell alloc]

initWithStyle:UITableViewCellStyleDefault

reuseIdentifier:SimpleTableIdentifier] autorelease];

}

NSUInteger row = [indexPath row];

if ([dataSet count] - 1 >= row)

{

// Create a object from the NSMutableArray appData

AppResultsData *appResultsDataDisp = [dataSet objectAtIndex:row];

// Compose a NSString to show UITableViewCell cell

NSString *rowText = [[NSString alloc ] initWithFormat:@"%@ - %@ - %@ - %@ - %@", appResultsDataDisp.RESULT_AMOUNT,appResultsDataDisp.CSU,appResultsDataDisp.MDC_IN_SI,appResultsDataDisp.RESULT_UNIT,
appResultsData.RESULT_DATE];

// Set UITableViewCell cell

cell.textLabel.text = rowText;

cell.textLabel.font = [UIFont boldSystemFontOfSize:14];

// Release alloc vars

[rowText release];

}

return cell;

}

 

Top of Page

Define the User Interface

The final step needed to tie everything together is to map the user interface to the methods just created. In the Navigator pane select “MainStoryboard.storyboard”. From the interface builder control drag the Table View to the View Controller and select the dataSource from the pop dialog box.

Select the Show the Assistant editor button. Then make sure that “ViewController.m” is selected in the right pane. From the Interface builder to the ViewController.m source code do the following:

  1. Control drag the “Prev” button to the method prevAction (the whole method should be highlighted and then release the button).
  2. Control drag the “Next” button to the method nextAction (the whole method should be highlighted and then release the button).

Top of Page

Run the Application

Run the application by clicking the “Run” button in xCode. Make sure iPhone 5.0 Simulator is the selected scheme like below.

run the app on iPhone

The iPhone simulator should start and display the following.

iPhone - 1st RadNet data view

Click on the “Analyte ID” text box and type “PU239.” Click the “Query” button and it will return a list of results.

iPhone - 2rd RadNet data view

Clicking the “Next” button will show the next 10 results.

iPhone - 3rd RadNet data view

Top of Page

Locate More Information on Envirofacts Radiation (RadNet) Data

Each dataset has a dataset location path that gives the Uniform Resource Locator (URL) that will be needed to reach the Data. The sample code can be adjusted to get that data and display it as well. For more information on the RESTful Web services provided by the EPA go to Envirofacts Data Service API.

EF Data Service API

 

Top of Page

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

Leave a comment

Your email address will not be published. Required fields are marked *