Categories
Articles

XCode 4 IPhone Mountains of the USA Tutorial: Lesson 2 – Load XML Data

<== Lesson 1 || Overview || Lesson 3 ==>

In this lesson you will make a requests for the Mountain data from a web site. The data is returned in an XML format. Then for testing you will display the raw XML on the phone screen and also display the XML data in the XCode console.

Screen With XML Loaded From Web

The main goal is to learn to use the NSURL, NSURLRequest, NSURLConnection and NSMutableData classes.

NSURL defines a URL for XCode. NSURLConnection establishes a connection to a server and manages the data to and from that server. NSURLRequest defines a network request along with data to send. NSMutableData stores any returning data.

When you load data from the web or any indeterminate process, you will want to include an activity indicator. So we will add a UIActivityIndicatorView that is the common activity indicator for Mac applications.

To see the data on the phone screen, we will use the UITextView which is a scrollable text component. In future lessons, we will replace the UITextView with a scrolling list of mountains in the XML data we receive.

You will need a web server to complete this and all future lessons in this tutorial. The tutorials use a web server with PHP that reads a comma delimited file containing the mountain data. The XML that the PHP script returns is included in this post should you not have PHP on your server. I will show you how to use that instead of the provided PHP script. However in future lessons we will want to ask the server for just partial data and we need a program to do that. Keep in mind you can also put the mountain data into a database on the server.

Source Download

  1. Starting XCode Project. This is the lesson 1 project completed.
  2. PHP and CSV Files. Script to read data file and selects by elevation and returns XML.
  3. Mountain XML Data. Alternative to hosting PHP script.
  4. Completed XCode 4 Project

[ad name=”Google Adsense”]

Step 1: MainViewController.h – Define properties and methods.

Download and uncompress the Starting XCode Project file and open in XCode.

Select the MainViewController.h in the project navigation window on the left and add the highlighted lines.

Line 4 is a constant for the URL to the PHP script or the XML file if you choose not to host the PHP script. More on these choices in this post when we get to those files.

The app will enable and disable the UIButton searchButton, so we need to include it for reference in code.

The UIActivityIndicatorView and UITextView are being added and are also referenced from our UI. The UIActivityIndicatorView will need to be hidden and revealed when we are not and are loading data from the server as well starting and ending its animation. So we need to make it an IBOutlet.

The UITextView will be updated with data coming in from the server and so it also needs to be an IBOutlet.

The MSMutableData is needed to capture the data coming in from the server in a raw format.

Your implementation code will call for disabling and enabling the search button and hiding and unhiding the activity indicator in more than one place in the code. Line 26 defines a method you will use so you do not have to repeat this UI state changing code in more than one place. The method receives an int parameter to define the state of the UI components. You will define their values in the implementation code.

//
//
//
#define kTextURL    @"http://YOUR_DOMAIN/PATH_IF_ANY_TO_SCRIPT/PHP_SCRIPT_OR_XML_FILE"

#import &lt;uikit uikit.h=""&gt;&lt;/uikit&gt;

@interface MainViewController : UIViewController
{
    UIButton                *searchButton;
    UIActivityIndicatorView *activityIndicator;
    UITextView              *resultsTextView;

    NSURLConnection         *urlConnection;
    NSMutableData           *receivedData;

}
@property (nonatomic, retain) IBOutlet UIButton                 *searchButton;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView  *activityIndicator;
@property (nonatomic, retain) IBOutlet UITextView               *resultsTextView;

@property (nonatomic, retain) NSURLConnection *urlConnection;
@property (nonatomic, retain) NSMutableData *receivedData;

-(IBAction) startSearch:(id)sender;
- (void) setUIState:(int)uiState;
@end

Step 2: MainViewController.m – Add Properties and Constants

This step basically is the implementation housekeeping prerequisites.

You add the getter and setters for the properties on lines 4 to 9 using synthesize.

Lines 12 and 14 provide constants for states of the view that are used in the setUIState method we defined in the last step. Those places in the code can make the code more readable when calling the setUIState.

#import "MainViewController.h"

@implementation MainViewController
@synthesize searchButton;
@synthesize activityIndicator;
@synthesize resultsTextView;

@synthesize urlConnection;
@synthesize receivedData;

// State is loading data. Used to set view.
static const int LOADING_STATE = 1;
// State is active. Used to set view.
static const int ACTIVE_STATE = 0;

Step 3: MainViewController.m – Memory Management Housekeeping

Add the memory release for the searchButton, activityIndicator, activityIndicator, resultsTextView, urlConnection and receivedData in the dealloc method.


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)dealloc
{
    [searchButton release];
    [activityIndicator release];
    [resultsTextView release];
    [urlConnection release];
    [receivedData release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

Step 4: MainViewController.m – Navigation Top Bar Title Updated

On line 47 you might want to update the title so you are not confused when viewing the app.

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [self setTitle:@"USA Mountains Lesson 2"];
}

Step 5: MainViewController.m – More Memory Management

In the viewDidUnload method add these lines to release the subviews you are going to link to this view in the UI.

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.searchButton = nil;
    self.activityIndicator = nil;
    self.resultsTextView = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

Step 6: MainViewController.m – Update the startSearch Method to Fetch Server Data

The startSearch method is already linked to our searchButton from the last tutorial. You have the code below to get the UI in the state for loading in progress, to make a request to the data source on the server and take needed steps based on the success or failure of that connection.

Line 69 is calling a method you will add in the next step to set the UI state. Your constant LOADING_STATE was defined in the last step.

Line 71 creates a NSString for the URL. In a future lesson you are going to concatenate a parameter to send along with the URL and now this line is ready for that.

[ad name=”Google Adsense”]

The NSURLRequest object named req is created on line 74.

The instance object named urlConnection on line 77 is your NSURLConnection. It does all the work for communicating with the server.

You see on line 77 it is using our NSURLRequest req object and also sending the delegate message to make this class, self, its delegate. That means urlConnection can call NSURLConnection methods you add to this class to take action needed to handle notifications such as successful completion or failure.

For this lesson you need to add four methods to handle the NSURLConnection messages didReceiveResponse, didReceiveData, didFailWithError and connectionDidFinishLoading. You will do that just after creating our setUIState method.

Lines 79 to 83 handle a successful connection. A NSMutableData object is created and assigned to the class receivedData NSMutableData object that in later code you will convert to readable XML for display.

Should the connection fail, lines 85 to 97 display a UIAlertView with the error information. Generally you will want to change that to something more meaningful to the user.

#pragma mark - UI Interface
-(IBAction) startSearch:(id)sender
{
    NSLog(@"startSearch");
     // Change UI to loading state
    [self setUIState:LOADING_STATE];
    // Create the URL which would be http://YOUR_DOMAIN_NAME/PATH_IF_ANY_TO/get_usa_mountain_data.php?elevation=12000
    NSString *urlAsString = [NSString stringWithFormat:@"%@", kTextURL ];

    NSLog(@"urlAsString: %@",urlAsString );
    NSURLRequest *req = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:urlAsString]];
    // Create the NSURLConnection con object with the NSURLRequest req object
    // and make this MountainsEx01ViewController the delegate.
    urlConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self];
    // Connection successful
    if (urlConnection) {
        NSMutableData *data = [[NSMutableData alloc] init];
        self.receivedData=data;
        [data release];
    }
    // Bad news, connection failed.
    else
    {
        UIAlertView *alert = [
                              [UIAlertView alloc]
                              initWithTitle:NSLocalizedString(@"Error", @"Error")
                              message:NSLocalizedString(@"Error connecting to remote server", @"Error connecting to remote server")
                              delegate:self
                              cancelButtonTitle:NSLocalizedString(@"Bummer", @"Bummer")
                              otherButtonTitles:nil
                              ];
        [alert show];
        [alert release];
    }
    [req release];

}

Step 7: MainViewController.m – Create the UI State Setting Method setUIState

This is your custom method to set the states of the UI components.

The UIButton has an alpha and enabled property. For your UIButton searchButtonobject, the alpha value is toggled between 50% and 100% and its enabled state is also toggled between true and false.

The UIActivityIndicatorView has methods on lines 108 and 116 for starting and stopping their animation. There is also a property hidesWhenStopped that you will set in the UI design that handles the hiding and showing of our UIActivityIndicator.

-(void) setUIState:(int)uiState;
{
    // Set view state to animating.
    if (uiState == LOADING_STATE)
    {
        searchButton.enabled = false;
        searchButton.alpha = 0.5f;
        [activityIndicator startAnimating];

    }
    // Set view state to not animating.
    else if (uiState == ACTIVE_STATE)
    {
        searchButton.enabled = true;
        searchButton.alpha = 1.0f;
        [activityIndicator stopAnimating];
    }
}

Step 8: MainViewController.m – Clear Received Data When Connection Is Established

You learned about pragma marks in the last lesson. You have 4 NSURLConnection related methods to add and this mark on line 119 is an easy way in XCode to get to where you are placing them in the code.

The connection didReceiveResponse method occurs when a connection is established. When that happens, your data communication starts over. To be on the safe side of it occurring more than once, you clear the NSMutableData object from any previous incomplete attempts. Consider this a boilerplate block you always include in code.

#pragma mark - NSURLConnection Callbacks
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [receivedData setLength:0];
}

Step 9: MainViewController.m – Accumulate Data Being Received

The NSURLConnection calls the connection didReceiveData method as data arrives and is ready for use. This is called as often as needed depending on the amount of data. The code you need here is to append the data received to your NSMutableData object.

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [receivedData appendData:data];
}

Step 10: MainViewController.m – Handle Network Connection Failure

The connection didFailWithError NSURLConnection call back method is where you handled the failure of the data transmission. In your case the code displays a UIAlertView with information from the NSError class error object passed in for learning purposes. A better user error should be considered for a released app.

You can use the NSError class to take different action based on the type of error. This is over the scope of this tutorial.

[ad name=”Google Adsense”]

There is some housekeeping such as calling the connection object release method and terminating the NSMutableData receivedData property.

The last line of code calls the sertUIState method with the ACTIVE_STATE value so the UI again appears available for another search.

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [connection release];
    self.receivedData = nil; 

    UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:@"Error"
                          message:[NSString stringWithFormat:@"Connection failed! Error - %@ (URL: %@)", [error localizedDescription],[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]]
                          delegate:self
                          cancelButtonTitle:@"Bummer"
                          otherButtonTitles:nil];
    [alert show];
    [alert release];
    // Change UI to active state
    [self setUIState:ACTIVE_STATE];
}

Step 11: MainViewController.m – Handle Network Connection Successful Completion

This final method is called when all the data is successfully loaded. The NSMutableData receivedData object is converted to a NSString on line 147.

On line 151 the UITextView text property resultsTextView is set to the data as a NSString. One the previous line the same is displayed in the XCode console window.

After that the NSURLConnection connection variable is released and the receivedData NSMutable object is truncated.

Your last line has the same task of setting the UI back to a state that the user can search again.

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // Convert receivedData to NSString.
    NSString *receivedDataAsString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];

    // Trace receivedData
    NSLog(@"%s - %@", __FUNCTION__, receivedDataAsString);
    resultsTextView.text = receivedDataAsString;
    [receivedDataAsString release];

    // Connection resources release.
    [connection release];
    self.receivedData = nil;
    // Change UI to active state
    [self setUIState:ACTIVE_STATE];
}

Step 12: MainViewController.xib – Add the Activity Indicator

Open the MainViewController.xib in the Project navigator and drag an Activity Indicator from the Objects library in the bottom right to place it under the button with the Search label.

Activity Indicator View

Be sure you keep the Activity Indicator you placed selected while completing the next three tasks.

Select the size panel in the top right and set the x and y values as shown here.

Activity Indicator Size Inspector

Select the Properties inspector and set the style to Large White and check the Behavior Hides When Stopped.

Activity Indicator Properties

In the Connections Inspector panel drag from the “New Referencing Outlet” in the “Referencing Outlets” group to the File Owner’s icon and release the mouse. Then select activityIndicator. You defined activityIndicator in your MainViewController code as a UIActivityIndicatorView.

Here is how the Connections Inspector will look when you are done.

Activity Indicator Connection Inspector

Step 13: MainViewController.xib – Add the TextView

You are adding a TextView that in a future tutorial you replace with a TableView. So there is no need to get heavily invested in how it looks.

Now drag a TextView from the Objects library in the bottom right to place it under the button with the Activity Indicator.

Text View

Keep the TextView you placed selected while completing the next two tasks.

Select the size panel in the top right and set the X, Y, Width and Height values as shown here.

Text View Size Inspector

In the Connections Inspector panel drag from the “New Referencing Outlet” in the “Referencing Outlets” group to the File Owner’s icon and release the mouse. Then select resultsTextView defined activityIndicator in your MainViewController code as a UITextView.

Your Connections Inspector should appear as follows.

Text View Connection Inspector

Step 14: MainViewController.xib – Review the Changes

First you can check the layout looking as follows.

MainViewController Design Window Complete

If you select the Connections inspector and then the File Owner’s icon you should see the following. If so you are good to go.

File Owner’s Connection Inspector

Step 15: PHP Server Script or XML File

This IPhone app loads XML data from a server. The Source Download includes an XML file you can use for this lesson.

However, the longer term of the Tutorial will request a query of the data from the server and at that point you can use the PHP script provided. I suggest you use that with this lesson so you are set up. But if you do not have a PHP script enabled server, you can use the XML file for a few more lessons.

Detailing how the PHP script works is beyond the scope of this tutorial. However what you should know it reads a CSV file. Here is a snippet of the file. The name used in the PHP script is mountain_data.csv.

Mount McKinley,20320, 63.0690,-151.00063
Mount Saint Elias,18008,60.2927,-140.9307
Mount Foraker,17400,62.9605,-151.3992

Then the PHP script returns XML. This is a snippet of what the XML data looks like when returned.

&lt;!--?xml version="1.0" encoding="UTF-8"?--&gt;
&lt;mountains source="http://en.wikipedia.org/wiki/Table_of_the_highest_major_summits_of_the_United_States" elevation_min="12000" count="100"&gt;
  &lt;mountain_item id="1" name="Mount McKinley" elevation="20320" lat=" 63.0690" lon="-151.00063"&gt;
  &lt;mountain_item id="2" name="Mount Saint Elias" elevation="18008" lat="60.2927" lon="-140.9307"&gt;
  &lt;mountain_item id="3" name="Mount Foraker" elevation="17400" lat="62.9605" lon="-151.3992"&gt;
&lt;/mountain_item&gt;&lt;/mountain_item&gt;&lt;/mountain_item&gt;&lt;/mountains&gt;

This XML you will learn to parse in a future tutorial.

This is the PHP script. The name I used for the script was get_mountain_data.php. You can name it what you like.

&lt;!--?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" );
header("Cache-Control: no-cache, must-revalidate" );
header("Pragma: no-cache" );
header("Content-Type: text/xml; charset=utf-8");
// XML to return.
$xml = '';
// Counter for number of mountains returned.
$mountain_count = 0;
// Filter mountains equal to or above this value. 
$elevation_min = 12000;
// Check for elevation parameter as a integer.
if ($_REQUEST['elevation_min'] &amp;&amp; intval($_REQUEST['elevation_min']))
{
	$elevation_min = intval( $_REQUEST['elevation_min']);
}
// Each element contains data for one mountain.
$mountains = array();
// Read a CVS file containing mountain data.
$mountain_data_lines = file('mountain_data.csv');
// Each line read .
foreach($mountain_data_lines as $line) 
{
	// Strip newline at end of line and break line by comma delimiter and 
	// append to $mountains.
	$mountains[] = explode( ',', rtrim($line));
}
// Each mountain.
foreach ($mountains as $value)
{
	// Mountain elevation equals or exceeds the filter value.
	if ( intval($value[1]) --&gt;= $elevation_min  )
	{
		$mountain_count++;
		// Create the mountain_item node.
		$xml .= '&lt;mountain_item ';="" $xml="" .="id = &amp;quot;" $mountain_count="" '"="" $value[0]="" $value[1]="" $value[2]="" $value[3]="" ;&lt;="" p=""&gt;
&lt;/mountain_item&gt;

	}
}
// Add mountains close node.
$xml .= '';
// Create mountains open node.
$xml_mountains = '&lt;mountains ';="" $xml_mountains="" .="source = &amp;quot;http://en.wikipedia.org/wiki/Table_of_the_highest_major_summits_of_the_United_States&amp;quot; " ;="" $elevation_min="" '"="" $mountain_count="" ;&lt;br=""&gt;
// Add mountains open node.
$xml = $xml_mountains . $xml;
// Return xml
echo $xml;
?&amp;gt;

<== Lesson 1 || Overview || Lesson 3 ==>

Categories
Articles

XCode 4 IPhone Mountains of the USA Tutorial: Overview

Welcome to the tutorial on creating the Mountains of the USA IPhone using XCode. The links to the completed lessons are located at the end of this post.

The tutorial examples uses the UINavigationController to manage the two screens. I built the first tutorial using a Window-Based Application project and then added the UINavigationController rather than use a Navigation Based project. This helped me understand the wiring of controllers to their interface counterparts and I believe provided a bit more flexibility. I learned to do this with Beginning iPhone 4 Development: Exploring the iOS SDK which was crucial to cracking the mysteries in writing IPhone apps.

The app will parse XML data containing the name, elevation, latitude and longitude of the highest 100 mountains in the USA. The XML data is loaded from a web server PHP script that allows for returning all 100 mountains or a selection above a specific elevation in feet. Then the location of any mountain is displayed in a map view.

Search Screen

Detail Screen

The first screen contains the user input to search for USA mountains based on their elevation and displays the results in a UITableView. Touching a mountain the UITableView opens the second screen where you can see the location of the mountain in a MapView with an MKAnnotationView showing the pin location on the map and a title.

Prerequisites: This is designed for beginners who have experimented with XCode and IPhone projects and who want work through an example that connects concepts into a useful app.

You need to have XCode installed. I used XCode 4 and IOS 4.2 for the tutorial projects. You can use XCode 3 however many screens and menus have changed for the better I might add which will make you dig a bit to find a panel or window. Otherwise the functionality you need is the same.
[ad name=”Google Adsense”]
You need to know how to build a basic hello world XCode IPhone project and run in the Simulator. You should have some basic practice using Interface Builder and adding IBOutlets and IBActions in Objective C.

You need to be a practicing programmer in some language. You do not need to be a ninja. A basic understanding of Objective C is helpful but if you have programming background, you should pick up on the Objective C nuances.

IOS Classes Used: In the tutorial you use the UINavigationController, UITableView, UITableViewCell, UITableViewCellStyleDefault, MKMapView, MKAnnotationView, MKPinAnnotationView, NSNumber, NSNumberFormatter, NSNumberFormatterDecimalStyle, UIActivityIndicatorView, UISlider, NSMutableData, NSMutableArray, UIButton, NSString, NSUInteger, CLLocationCoordinate2D, UIAlertView and NSXMLParser.

[ad name=”Google Adsense”]
Currently there are nine lessons and this will provide a table of contents for them as they get posted. You can register below and you will get notifications when new lessons are posted.

Categories
Articles

XCode IPhone Client Server Echo Hello Example Using PHP


This is a basic IPhone client server example using PHP. This is a duplication of a Titanium example I created February 27th: see Titanium IPhone Client Server Echo Hello Example Using PHP.

This XCode example like the Titanium version simply sends text entered on the phone and returns it with the word “Hello” prefixed. It uses HTTP and the POST protocol. The server app is a simple PHP script.

First Launch

This is the IPhone screen when the application first runs.

The text input will show the keyboard when typing. The send button closes the keyboard and starts the HTTP session. There is no error handling should the connection fail or the server fail.

This is an asynchronous example. So other operations could occur while the request to server is in process. For example the send button can be pressed over and over. So an activity indicator would be a nice improvement.

Source Download
XCode 4 Project

I used the IOS “View-based Application” when creating a new project in XCode. All the coding is in the AnimatedDieFaceViewController UIViewController.

NSUrlClientServerURLVariablesEx01ViewController.h

This sets out the interface for the view controller.

Line 2 contains a constant for the PHP script that received the name and returns the response. You need to replace the YOURDOMAIN and the PATH_IF_ANY_TO/ for your project. The php script is included in the download and is also listed at the end of this post.

The responseTextView is updated with the response from test02.php.

The receivedData NSMutableData object handles the byte data that will come from the server.
[ad name=”Google Adsense”]
The two IBOutlet variables for the controller to access UI components. The controller needs to read the user input from nameTextField and needs to update responseTextView with data received from the server.

The one IBAction method kicks off the client server process with the send button.

#import <UIKit/UIKit.h>
#define kTextUrl @"http://www.YOURDOMAIN.com/PATH_IF_ANY_TO/echo_hello.php"

@interface NSUrlClientServerURLVariablesEx01ViewController : UIViewController {
    UITextField     *nameTextField;
    UITextView      *responseTextView;
    NSMutableData   *receivedData;
}
@property (nonatomic, retain) IBOutlet UITextField *nameTextField;
@property (nonatomic, retain) IBOutlet UITextView *responseTextView;
@property (nonatomic, retain) NSMutableData *receivedData;

- (IBAction)makeRequest;

@end

NSUrlClientServerURLVariablesEx01ViewController.m

This sets out the interface for the view controller. Five methods are used to handle the request to and response from the server.

The makeRequest method initiates the request to the server is on line 10.

First Launch

Four methods on lines 91, 99, 106 and 127 are required because line 27 makes this controller the delegate for NSURLConnection.

The makeRequest method on line 10 is fired from the send button. It performs two tasks. One is assembling the parts of the nsMutableURLRequest object such as the protocol and name value pair parameter. The POST protocol is set on line 18 and line 20 creates the name=whatever_the_user_enters name value pair needed for the server script. The second task is making NSURLConnection and testing if it can work.

Lines 91 – 97 contains the connection didReceiveResponse method. This is needed to clear the data received because of the nature of multiple times it can be called.

The connection didReceiveData method on line 99 – 104 starts collecting the byte data received over the network.

If there is a problem with the connection the connection didFailWithError method occupying lines 106 to 125 is called. Here you can create a better UIAlertView and perhaps relegate the error codes to a trace log.

Finally should everything go well and all the data is received, the connectionDidFinishLoading method on lines 127 – 139 updates the UITextView with our results.

//
#import "NSUrlClientServerURLVariablesEx01ViewController.h"

@implementation NSUrlClientServerURLVariablesEx01ViewController
@synthesize nameTextField;
@synthesize responseTextView;
@synthesize receivedData;

// Send button Touch Up Inside
- (IBAction)makeRequest
{
    NSLog(@"%s", __FUNCTION__);
    //Allocate NSURL object
    NSURL *nsURL = [[NSURL alloc] initWithString:kTextUrl];
    // Allocate NSMutableURLRequest
	NSMutableURLRequest *nsMutableURLRequest = [[NSMutableURLRequest alloc] initWithURL:nsURL];
    // Set HTTP method to POST
	[nsMutableURLRequest setHTTPMethod:@"POST"];
    // Set up the parameters to send.
    NSString *paramDataString = [NSString stringWithFormat:@"%@=%@", @"name", nameTextField.text];
    NSLog(@"%s - paramDataString: %@", __FUNCTION__, paramDataString);
    // Encode the parameters to default for NSMutableURLRequest.
	NSData *paramData = [paramDataString dataUsingEncoding:NSUTF8StringEncoding];
    // Set the NSMutableURLRequest body data.
	[nsMutableURLRequest setHTTPBody: paramData];	
    // Create NSURLConnection and start the request.
    NSURLConnection *nsUrlConnection=[[NSURLConnection alloc]
                                    initWithRequest:nsMutableURLRequest 
                                    delegate:self];
    // Successful connection.
    if (nsUrlConnection) {
        NSMutableData *data = [[NSMutableData alloc] init];
        self.receivedData=data;
        [data release];
    } 
    // Unsuccessful connection.
    else {
        responseTextView.text =  [NSString stringWithFormat :@"Unable to make connection!"] ;
    }  
    // Clean up
	[nsURL release];
	[nsMutableURLRequest release];
    // Close keypad.
    [nameTextField resignFirstResponder];
    

}
- (void)dealloc
{
    [nameTextField release];
    [responseTextView release];
    [receivedData release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];
}
*/

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    self.nameTextField = nil;
    self.responseTextView = nil;
    self.receivedData = nil;
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark -
#pragma mark NSURLConnection Callbacks
// Connection response.
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{
    NSLog(@"%s - Response Code: %d\n", __FUNCTION__, [(NSHTTPURLResponse *)response statusCode]);
    NSLog(@"%s - Content-Type: %@\n",  __FUNCTION__, [[(NSHTTPURLResponse *)response allHeaderFields] objectForKey:@"Content-Type"]);
    // Clear the NSMutableData receivedData.
    [receivedData setLength:0];
}
// You got data.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{
    NSLog(@"%s", __FUNCTION__);
    // Append the data to our NSMutableData receivedData.
    [receivedData appendData:data];
}
// Sorry Dude, connection failed gloriously.
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{
    NSLog(@"%s", __FUNCTION__);
    
    // Create noxious error message.
    NSString *errorMessage = [[NSString alloc]initWithFormat: @"Connection failed! Error - %@ (URL: %@)", [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]];
    // Throw up a noxious error message.
    UIAlertView *alert = [[UIAlertView alloc] 
                        initWithTitle:@"Sorry Dude!"
                        message:errorMessage 
                        delegate:self
                        cancelButtonTitle:@"Close"
                        otherButtonTitles:nil];
    [alert show];
    // Clean up
    [connection release];
    self.receivedData = nil; 
    [alert release];
    [errorMessage release];
}
// Finally the data is completely loaded.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"%s", __FUNCTION__);
    // Encode received data to NSUTF8StringEncoding
    NSString *receviedDataAsString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
    NSLog(@"%s - receviedDataAsString: %@", __FUNCTION__, receviedDataAsString);
    // Show received data in the responseTextView.
    responseTextView.text = receviedDataAsString;
    // Clean up.
    [receviedDataAsString release];
    [connection release];
    self.receivedData = nil;
}
@end

[ad name=”Google Adsense”]

NSUrlClientServerURLVariablesEx01ViewController.xib

UIView

This is the layout of the interface.

There is another UIView behind the UILabel, UITextField and UIButton. The UIView background is set to a light gray to give a panel effect.

The UITextField is preloaded with a value.

Below the UIView at the top is a UITextView. It is also preloaded with a message on how to use the app.

 
 
 
 
 
 
 
 
 
 
 
NSUrlClientServerURLVariablesEx01ViewController IBOutlets and IBActions

The IBOutlets are for the UITextField and the UITextView so their properties in the controller code can be read or changed. The UITextField is read on line 20. The UITextView is changed on line 134.

The view outlet was set when I choose the IOS View-based Application to create the XCode project.

The IBActions are for the one UIButton when the Touch Up Inside event is initiated. You can see the method makeRequestlinked to the UIButton.

[ad name=”Google Adsense”]
echo_hello.php – Server Script
Very simple echo script. The name identifier on line 20 of NSUrlClientServerURLVariablesEx01ViewController.m is picked up in the PHP $_REQUEST object as you might expect. The value of $_REQUEST[‘name’] is appended to ‘Hello’ plus a space and returned without any data markup. Nothing very fancy.

<?php
echo "Hello " . $_REQUEST['name'] . "!";
?>

Categories
Articles

“Anyone Can Write an App” Mobile Development Platform List


Mobile development products are springing up forming a new industry. These are called mobile frameworks, development tools and mobile kits for example. Some embrace an enterprise level and some just client side. The products are aimed at the need to leverage skills of developers to build applications for devices cheaper and quicker.

To help you keep up, I am maintaining this list as the industry unfolds and will update as I find new products. There are links to the web site and to product overview videos or demo videos.

There is no particular ranking to the list. However those vendors that have clear links to overview videos and have a good hello world or the like video are listed first. It shows enthusiasm to communicate and is a criteria for any comparisons. Other than that the list is somewhat in the order I discovered the vendor. It is important for all vendors to know that ease of use depends on the simple atomic how to videos to win minds of developers. The faster you get into the mind of a developer the more likely you win that mind.

The List

  1. WireNode is a mobile website management platform. It boasts delivery to any device with their mobile core called Anypage ©. They claim it supports: Nokia, Sony Ericsson, Siemens, LG, Motorola, Apple (iPhone), Palm (Treo), RIM (BlackBerry) and many Windows CE devices with outputs in the WAP (WLM), XHTML mobile profile, XHTML basic, cHTML and standard HTML formats. There is a mobile page editor which allows integration with PostgreSQL, Struts (for page flow), Red Hat, Apache, and Hibernate (as database framework). Current customer listing examples are not impressive and lack the polish of a JQuery Mobile UI. However this is an example of offering trends where a CMS, or at least back end, plus multiple front end delivery with same content. Web site was not clear about tablets.
  2. Cabana This is built in HTML5 and provides a drag and drop wireframe type of app development tool. This visual approach also include RESTful JSON and XML APIs, and you can bind them to your user interface. It appears Cabana handles store distribution and updates are automatic which may indicate you are really creating a web app. Also they have a Fan Page Mobilizer tool that lets you take your Facebook Fan Page and convert it to an app.
  3. Marmalde Not only promising a cross deployment solution but includes converting IOS apps to Andriod and covers Kindle Fire. Here is their line: “Marmalade is the world’s most powerful SDK for the creation of richer apps and games on iOS, Android and other platforms. Marmalade’s unique technical architecture offers maximum performance through true native code. “
  4. AMPchroma from Antenna Software. AMPchroma is the first cloud platform for managing the entire mobile lifecycle. All design, development, management, and analytics functionality are presented as a suite of software modules accessible from a user-friendly web interface.
  5. Kendo UI | Demo | Kendo UI Mobile helps developers build apps and sites for mobile devices that always look native. On iOS, Kendo UI Mobile widgets look native to iOS. On Android, Kendo UI Mobile widgets look native to Android. Automatically. Kendo UI Mobile detects the device and applies the proper styling.
  6. Appcelerator Titanium | Video Demo | A free and open source application development platform, Titanium lets you create native mobile, tablet and desktop application experiences using existing web skills like Javascript, HTML, CSS, Python, Ruby, and PHP.
  7. Red Foundry | Video Demo | Creating, developing mobile IPhone app is free as is publishing yourself for apps started withing a limited time offering. Publishing the app through Redfoundry has a monthly cost but they handle all the details. Android expected Q2 2011.
  8. RhoMobile | Video Demo | Rhodes is Ruby-based framework that enables the creation of native apps for major smartphone operating systems (iPhone, Windows Mobile, RIM, Symbian and Android). Developers can create native iPhone and iPad apps from a Windows-based PC using in HTML, Javascript and Ruby.
  9. appMobi | Video Overview | Video Demo. HTML5, CSS and JavaScript to create mobile apps using their cloud. Uses WebKit based MobiUs browser to access native phone functionality.
  10. jQ.Mobil JQuery written from the ground up for mobile, HTML5 on IOS and Andriod device. In beta as of 1/18/12.
  11. Trigger.IO/ HTML5, CSS and JavaScript to create mobile apps free while in beta. Write once, submit to PhoneGap and download all the supported platforms ready for submission. Supported platforms currently IPhone Andriod, Symbian and Palm.
  12. PhoneGap HTML5, CSS3 and JavaScript to create mobile apps and the Trigger.IO service converts to native apps while retaining deployment to web browsers. Free conversion service has Trigger.IO branding on splash screen and in the description; and free conversion serviceis limited to free apps. Monthly fee service extends to paid apps and drops the in app Trigger.IO branding.
  13. Mobile Nation | Video Overview | Video Demos. Design, build and publish mobile apps for iPhone and Android devices using their web based environment. Use a QR code, their installed app and your device camera to load to your testing phone. Looks like a corker.
  14. MoSync | Video Demo | Open source SDK using C++ and a set of powerful APIs, you can harness the full power of modern smartphone platforms while still supporting Java ME devices using a single codebase. MoSync produces real native IPhone and Android applications, packaged and ready for distribution in each platforms’ native installation format.
  15. OpenPlug | Video Demo — Actionscript interestingly
  16. QT Nokia | Video Overview
  17. Adobe CS 5.5 | Video Demo with PhoneGap
  18. Jo HTML Mobile App Framework | Video Demo | JavaScript framework for HTML5 capable browsers and devices. It was originally designed to work on mobile platforms as a GUI and light data layer on top of PhoneGap. Since its creation, Jo has also been tested successfully as a lightweight framework for mobile browsers, newer desktop browsers, and even Dashboard widgets.
  19. LiveCode | Video Demo is on Home Page
  20. Whoop
  21. Corona
  22. BuzzTouch
  23. Appshed
  24. Senica Touch This is a Javascript library that produces the native look and feel of mobile devices. You would integrate with PhoneGap for device features like Accelerometer
  25. Kony Solutions
  26. Nimble Kit
  27. Service2Media
  28. AppMakr No Coding Required. Use the templates for loading data feeds such as blogs, video and photos. Customize with PhoneGap. Look and feel all customized from menu systems. Handles push notification service. Will publish using your developer account. Has a portfolio of accounts that have used this to publish apps.
  29. Tiggr This is a cloud based development tool with a software subscription service.
  30. StackMob Offers a mobile development sandbox environment with backend api for mobile apps remote data and remote services.
  31. JQTouch A JQuery plugin for mobile web development.
  32. JQuery Mobile HTML5-based user interface system for all popular mobile device platforms and built on the JQuery platform.
  33. IUI Video and demo.
  34. XUI A super micro tiny dom library for authoring html5 mobile web applications. Targeted builds for webkit, ie mobile, and blackberry
  35. Local Mobile Geared towards businesses needing to reach customers versus towards developers such as with SMS, QR and Ecommerce. They do all the work for hosting, at a fee, the app.
  36. AppFurnance is a set of online tools that help you to create all kinds of apps without having to be a programming genius. It gives you control to design interfaces, create location-aware experiences and, if you want to take it further, add your own JavaScript and produce exactly what experience you want.
  37. Codiqa Drag and drop approach to prototype, build, and manage fully functional mobile web apps with jQuery Mobile.
  38. Tiggzi HTML5 CSS PhoneGap cloud-based mobile app builder.

[ad name=”Google Adsense”]



Categories
Articles

IPhone Basic Dice Roller Animation Using XCode

This is a basic IPhone example that demonstrates an animated UIImageView. The example demonstrates how to take a sequence of images and animate them.

Ready to Animate State

To make the example interesting, I decided to use the roll of one die. This does not show a rolling 3D dice. Rather it is a sequential swapping of die faces on a single plane. When you start the die roll, you can choose when to stop. When the animation is stopped, I am using a random number to select which die value. As such the last animated die face is not the die face for the roll value. I set the animating fast enough for the simulator at least to make it difficult to see which die value was last animated when the stop button is released.

I also shows setting the user interaction states for when the die is being rolled and when it is not. I include some constants for determining the view state based on when the die is rolling or not. For example in this view the app is not animating so the roll button is enabled and the stop button is disabled.

The images for the die faces are very simple.

Source Download
XCode 4 Project

I used the IOS “View-based Application” when creating a new project in XCode. All the coding is in the AnimatedDieFaceViewController UIViewController.

AnimatedDieFaceViewController.h

This sets out the interface for the view controller.

The controller needs to set the enabled and alpha properties of the roll and stop button respectively named as rollButton and stopButton. To do this they are declared as IBOutlet so they can be linked up in the XIB file.

The rollDiceImageView UIImageView is where we will swap 6 images of die faces. Those are UIImage objects stored in the animationImages NSArray.

The method rollButtonPressed, stopButtonPressed, setAnimatingState, animateImages and stopAnimatingImages are explained with the implementation code.

#import <UIKit/UIKit.h>

@interface AnimatedDieFaceViewController : UIViewController {
    UIImageView *rollDiceImageView;
    UIButton *rollButton;
    UIButton *stopButton;
    NSArray *animationImages;

}
@property (nonatomic, retain) IBOutlet UIImageView *rollDiceImageView;
@property (nonatomic, retain) IBOutlet UIButton *rollButton;
@property (nonatomic, retain) IBOutlet UIButton *stopButton;
-(IBAction) rollButtonPressed:(id) sender;
-(IBAction) stopButtonPressed:(id) sender;
-(void) setAnimatingState:(int)animatingState;
-(void) animateImages;
-(void) stopAnimatingImages;
@end

[ad name=”Google Adsense”]

AnimatedDieFaceViewController.m

On lines 9 and 11 I declared two constants,ANIMATING_YES and ANIMATING_NO to indicate the animation state. Those are values to pass to setAnimatingState where the rollButton and the stopButton enabled and alpha properties are set.

In the viewDidLoad method starting on line 84, the animatingImages NSArray is populated with images.

Animating State

Also initial properties for the rollDiceImageView UIImageView are set including

  • image for the initial image when the app starts up.
  • animationImages set to our animatingImages NSArray.
  • animationDuration set to .5 or 1/2 of a second.
  • animationRepeatCount set to 0 to keep the animation running indefinitely.

When the rollButton is pressed, the rollButtonPressed method is called on line 13 which in turn calls the animateImages method on line 18. It is in animateImages the the view state is set and the animation is started. The view state is set so the roll button is disabled and the stop button is enabled.

On line 26 the stopButtonPressed method leads us to the stopAnimatingImages method on line 31. In this method we compute a random number rollValue for the dice roll using arc4random on line 38.

Then on line 40 rollValue is used to determine which image in the animationImages NSArray to assign to the image property of rollDiceImageView UIIMageView.

Line 42 calls setAnimatingState to reset the roll to an enabled state and stop button to a disabled state.

#import "AnimatedDieFaceViewController.h"

@implementation AnimatedDieFaceViewController
@synthesize rollDiceImageView;
@synthesize rollButton;
@synthesize stopButton;

// State is animating. Used to set view.
static const int ANIMATING_YES = 1;
// State is not animating. Used to set view.
static const int ANIMATING_NO = 0;

-(IBAction) rollButtonPressed:(id) sender
{
    NSLog(@"rollButtonPressed");
    [self animateImages];
}
-(void) animateImages
{
    NSLog(@"animateImages");
    //Set view to animating state.
    [self setAnimatingState:ANIMATING_YES];
    // Start the animation
	[rollDiceImageView startAnimating];
}
-(IBAction) stopButtonPressed:(id) sender
{
    NSLog(@"RotatingDiceEx01ViewController.stopButtonPressed");
    [self stopAnimatingImages];
}
-(void) stopAnimatingImages
{
    NSLog(@"RotatingDiceEx01ViewController.stopAnimatingImages");

    // Stop the animation.
    [rollDiceImageView stopAnimating ];
    // Generate a random number from 0 to 5;
    int rollValue =  arc4random() %  6  ;
    // Assign image from the animationImages NSArray using the rollValue as index.
    rollDiceImageView.image = [animationImages objectAtIndex:rollValue];
    //Set view to not animating state.
    [self setAnimatingState:ANIMATING_NO];
}
-(void) setAnimatingState:(int)animatingState
{
    NSLog(@"RotatingDiceEx01ViewController/setAnimatingState(...) - animatingState %i:", animatingState);
    // Set view state to animating.
    if (animatingState == ANIMATING_YES)
    {
        rollButton.enabled = false;
        rollButton.alpha = 0.5f;
        stopButton.enabled = true;
        stopButton.alpha = 1.0f;
    }
    // Set view state to not animating.
    else if (animatingState == ANIMATING_NO)
    {
        rollButton.enabled = true;
        rollButton.alpha = 1.0f;
        stopButton.enabled = false;
        stopButton.alpha = 0.5f;
    }
}
- (void)dealloc
{
    [animationImages release];
    [rollDiceImageView dealloc];
    [rollButton dealloc];
    [stopButton dealloc];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    NSLog(@"RotatingDiceEx01ViewController.viewDidLoad");
    // Build an array of UIImage objects.
    animationImages = [[NSArray arrayWithObjects:
                        [UIImage imageNamed:@"die_face_01.png"],
                        [UIImage imageNamed:@"die_face_02.png"],
                        [UIImage imageNamed:@"die_face_03.png"],
                        [UIImage imageNamed:@"die_face_04.png"],
                        [UIImage imageNamed:@"die_face_05.png"],
                        [UIImage imageNamed:@"die_face_06.png"],
                        nil] retain ];
    // Set the starting image.
    rollDiceImageView.image = [UIImage imageNamed:@"die_face_01.png"];
    // Initialize the animation properties
    rollDiceImageView.animationImages = animationImages; // NSArray of UImage objects.
	rollDiceImageView.animationDuration = .5; // Default = .033333 1/30 sec
	rollDiceImageView.animationRepeatCount = 0; // 0 = continuous

    [super viewDidLoad];
}
- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.rollDiceImageView = nil;
    self.rollButton = nil;
    self.stopButton = nil;

}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
@end

[ad name=”Google Adsense”]

AnimatedDieFaceViewController.xib

AnimatedDieFaceViewController UIView

This is the layout of the interface.

The UIButton with the Stop caption has its enabled property unchecked and its alpha property set to 0.5;

The dimensions of the UIImageView is set to 100 by 100. Each of the die face images are 100 by 100. The UIImageView is dead center in the UIView.

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
AnimatedDieFaceViewController IBOutlets and IBActions

The IBOutlets are for the two UIButtons and the UIImageView so their properties in the controller code can be changed. You can see on lines 40, 97, 99, 100 and 101 setting rollDiceImageView UIImageView properties. In the setAnimatingState method starting on line 44 the alpha and enabled properties for the buttons are set.

The view outlet was set when I choose the IOS View-based Application to create the XCode project.

The IBActions are for the two buttons when the Touch Up Inside event is initiated. You can see the methods rollButtonPressed and stopButtonPressed linked to that event for each button.