Wednesday, November 7, 2012

UIView into UIImage. i.e. screen snapshot of a view

@interface UIView(Extended) 

- (UIImage *) imageByRenderingView;

@end


@implementation UIView(Extended)


- (UIImage *)imageByRenderingView
{   
    UIGraphicsBeginImageContext(self.bounds.size);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return resultingImage;
}

@end
 
 
Just Call:- 
 
UIImage *currImage = [self.view imageByRenderingView];
 

 
You can split your UIImage in two by using this code:
CGImageRef topOfImageCG =
         CGImageCreateWithImageInRect(currImage.CGImage,
                                      CGRectMake(0,
                                                 0,
                                                 currImage.size.width,
                                                 currImage.size.height / 2.0));

UIImage *topOfImage = [UIImage imageWithCGImage:topOfImageCG];

CGImageRelease(topOfImageCG);
  

Wednesday, October 31, 2012

Touch Began for particular CGRect and Rotating Image with finger moved


// sample code inside Touchesbegan method
CGRect tempRect = CGRectMake(x, y, width, height);
if (CGRectContainsPoint(tempRect, touchlocation)) 
{
    // do some thing
}
- (void)viewWillAppear:(BOOL)animated
{
    imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mycard_back_dark_bg.png"]];
   imageView2.frame=self.imageView.frame;
    
    imageView2.bounds = self.imageView.bounds;
    [self.view addSubview:self.imageView2];
    [self.view sendSubviewToBack:imageView2];
    
    UIImage *image = [UIImage imageNamed:@"mycard_back_dark_bg.png"];
    
    UIImageOrientation flippedOrientation = UIImageOrientationUpMirrored;
    
    
    
    switch (image.imageOrientation)
    {
        case UIImageOrientationUp:
                                   break;
            
        case UIImageOrientationDown:
                                    flippedOrientation = UIImageOrientationDownMirrored;
                                    break;
        case UIImageOrientationLeft:    
                                    break;
        case UIImageOrientationRight:
                                    break;
        case UIImageOrientationUpMirrored:
                                    break;
        case UIImageOrientationDownMirrored:
                                    break;
        case UIImageOrientationLeftMirrored:
                                    break;
        case UIImageOrientationRightMirrored:
                                    break;
            
           
    }
    UIImage * flippedImage = [UIImage imageWithCGImage:image.CGImage scale:image.scale orientation:flippedOrientation];
    
    self.imageView2.image=flippedImage;
    
    UILabel *cardNo= [[UILabel alloc] initWithFrame:CGRectMake(self.imageView.frame.origin.x+5, self.imageView.frame.origin.y+10, self.imageView.frame.size.width-30, self.imageView.frame.size.height/4)];
    
    [cardNo setText:@"5081 5988 1045 2318"];
    [cardNo setTextColor:[UIColor whiteColor]];
    [cardNo setBackgroundColor:[UIColor clearColor]];
    
    [self.imageView addSubview:cardNo];
    
   
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    
    
    
UITouch *touch = [touches anyObject];
CGPoint origin = [self.imageView center];
    
    // sample code inside Touchesbegan method
    CGRect tempRect = CGRectMake(0, 0, 320, 200);
    if (CGRectContainsPoint(tempRect, [touch locationInView:self.view]))
    {
        // do some thing
        CGFloat angle = angleBetweenLinesInRadians(origin, [touch previousLocationInView:self.view], origin, [touch locationInView:self.view]);
        
        // NSLog(@"angle %2f",angle);
        i=i+angle;
        
        // NSLog(@"value of i %f",i);
        self.imageView.layer.doubleSided=FALSE;
        
        //self.imageView2.hidden = YES;
        self.imageView.layer.transform=CATransform3DMakeRotation(i, 0.0, 0.1, 0.0);
        
        self.imageView2.layer.transform=CATransform3DMakeRotation(i, 0.0, 0.1, 0.0);
        
        //  NSLog(@"position.z %f",self.imageView.layer.zPosition);
        // NSLog(@"position.y %f",self.imageView.layer.position.y);
        
        CALayer* layer = [self.imageView.layer presentationLayer];
        float currentAngle = [[layer valueForKeyPath:@"transform.rotation.z"] floatValue];
        NSLog(@"currentAngle %f",currentAngle);
        
        CALayer* layer2 = [self.imageView2.layer presentationLayer];
        float currentAngle2 = [[layer2 valueForKeyPath:@"transform.rotation.z"] floatValue];
        NSLog(@"currentAngle2 %f",currentAngle2);
    }
    
    
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    
    CALayer* layer = [self.imageView.layer presentationLayer];
    float currentAngle = [[layer valueForKeyPath:@"transform.rotation.z"] floatValue];
    NSLog(@"currentAngle %f",currentAngle);
    
    if (currentAngle==0) {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.75];
        [UIView setAnimationDelay:0.0];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
         
         self.imageView.layer.transform=CATransform3DMakeRotation(0, 0.0, 0.1, 0.0);
         self.imageView2.layer.transform=CATransform3DMakeRotation(0, 0.0, 0.1, 0.0);
        
        [UIView commitAnimations];
        
        i=0;
        
    }else {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.75];
        [UIView setAnimationDelay:0.0];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        self.imageView.layer.transform=CATransform3DMakeRotation(3.14, 0.0, 0.1, 0.0);
        self.imageView2.layer.transform=CATransform3DMakeRotation(3.14, 0.0, 0.1, 0.0);
        
        [UIView commitAnimations];
        
       i=3.14;
    }
}
static inline CGFloat angleBetweenLinesInRadians(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint line2End) {
    
    CGFloat a = line1End.x - line1Start.x;
    CGFloat b = line1End.y - line1Start.y;
    CGFloat c = line2End.x - line2Start.x;
    CGFloat d = line2End.y - line2Start.y;
    
    CGFloat line1Slope = (line1End.y - line1Start.y) / (line1End.x - line1Start.x);
    CGFloat line2Slope = (line2End.y - line2Start.y) / (line2End.x - line2Start.x);
    
    CGFloat degs = acosf(((a*c) + (b*d)) / ((sqrt(a*a + b*b)) * (sqrt(c*c + d*d))));
    
    
    return (line2Slope > line1Slope) ? degs : -degs;    
}

Friday, June 1, 2012

MapKit and the MKMapView Class

Working with Maps on the iPhone with MapKit and the MKMapView Class

In the preceding chapters we spent some time looking at handling raw geographical location information in the form of longitude, latitude and altitude data. The next step is to learn about the presentation of location information to the user in the form of maps and satellite images. The goal of this chapter, therefore, is provide an overview of the steps necessary to present the iPhone iOS 5 application user with location, map and satellite imagery using the MapKit framework and, in particular, the MKMapView class.

Contents

[hide]













[edit] About the MapKit Framework

The MapKit Framework is based on the Google Earth and Google Maps data and APIs and provides iPhone developers with a simple mechanism for integrating detailed and interactive mapping capabilities into any application.
The core element of the MapKit framework from the point of view of the app developer is the MKMapView class. This class is a subclass of UIView and provides a canvas onto which map and satellite information may be presented to the user. Information may be presented in map, satellite or hybrid (whereby the map is superimposed onto the satellite image) form. The displayed geographical region may be changed manually by the user via a process of pinching stretching and panning gestures, or programmatically from within the application code via methods calls and property manipulation on the MkMapView instance. The current location of the device may also be displayed and tracked on the map view.
The MapKit framework also includes support for adding annotations to a map. This takes the form of a pin or custom image, title and subview that may be used to mark specific locations on a map.
Implementation of the MKMapViewDelegate protocol allows an application to receive notifications of events relating to the map view such as a change in either the location of the user or region of the map displayed or the failure of the device to identify the user’s current location or to download map data.

[edit] Understanding Map Regions

The area of the map that is currently displayed to the user is referred to as the region. This is defined in terms of a center location (declared by longitude and latitude) and span of the surrounding area to be displayed. Adjusting the span has the effect of zooming in and out of the map relative to the specified center location. The region’s span may be specified using either distance (in meters) or coordinate based degrees. When using degrees, one degree of latitude is equivalent to 111 km. Latitude, however, varies depending on the longitudinal distance from the equator. Given this complexity, the map view tutorial in this chapter will declare the span in terms of distance.

[edit] About the iPhone MKMapView Tutorial

The objective of this tutorial is to develop an iPhone application designed to display a map with a marker indicating the user’s current location. Buttons located in a navigation bar are provided to allow the user to zoom in on the current location and to toggle between map and satellite views. Through the implementation of the MKMapViewDelegate protocol the map will update as the user’s location changes so that the current location marker is always the center point of the displayed map region. Finally, a basic annotation will be implemented to mark a specific location on the map with a pin and title.

[edit] Creating the iPhone Map Tutorial

Begin by launching Xcode and creating a new iOS iPhone project named mapSample using the Single View Application template.

[edit] Adding the MapKit Framework to the Xcode Project

Since we will be making use of the MapKit framework during this tutorial the first step is to add the framework to the project. To achieve this, select the Build Phases tab on the mapSample summary panel and unfold the Link Binary with Libraries section. Click on the ‘+’ button, locate the MapKit.framework entry from the resulting list and click Add.

[edit] Declaring an Outlet for the MapView

Clearly since we plan on working with an MKMapView object in our iPhone iOS 5 application it will be necessary to declare an outlet for this object. Later in the tutorial we will add code to update the map based on changes to the user’s location. To do this it will also be necessary to implement the MKMapViewDelegate protocol within our view controller class. The application is also going to require a toolbar which we will reference via an outlet named toolBar. Finally, the code will require that the <MapKit/MapKit.h> file be imported. All these code changes may be implemented in the mapSampleViewController.h file as follows:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface mapSampleViewController : UIViewController {
    <MKMapViewDelegate>
{
        MKMapView *mapView;
        UIToolBar *toolBar;
}
@property (strong, nonatomic) IBOutlet MKMapView *mapView;
@property (strong, nonatomic) IBOutlet UIToolBar *toolBar;
@end
Having declared the outlet, add the corresponding synthesize directive to the mapSampleViewController.m file:
#import "mapSampleViewController.h"
@implementation mapSampleViewController
@synthesize mapView, toolBar;
.
.
@end

[edit]

Creating the MKMapView and Connecting the Outlet

The next step is to create an instance of the MKMapView class we will be using in our application and to add a toolbar instance to the user interface. Begin by selecting the mapSampleViewController.xib file so that the Interface Builder panel appears. Drag a Tool Bar from the Object Library and place it at the bottom of the view canvas. Next, drag and drop a Map View object onto the canvas and resize and position it so that it takes up the remaining space in the view above the toolbar:


Figure 48-1
If present, select the button in the toolbar labeled “Item” and press the Delete key on the keyboard to remove it from the design. Connect the mapView outlet to the object by Ctrl-clicking on the File’s Owner object and dragging the resulting line to the Map View object. Release the line and select mapView from the menu. Repeat these steps to map the toolbar outlet to the tool bar object.
Perform a test run of the application’s progress so far by clicking on the Run button in the Xcode toolbar. The application should run in the iOS simulator as illustrated in Figure 48-2:


Figure 48-2

[edit]

Adding the Tool Bar Items

Next, the two buttons need to be added to the navigation bar. This code will be placed in the viewDidLoad method located in the mapSampleViewController.m file. Now is also a good time to configure the mapView to display the user’s current location by setting the showsUserLocation property:
- (void)viewDidLoad
{
    [super viewDidLoad];
    mapView.showsUserLocation = YES;
    UIBarButtonItem *zoomButton = 
        [[UIBarButtonItem alloc]
         initWithTitle: @"Zoom"
         style:UIBarButtonItemStylePlain
         target: self
         action:@selector(zoomIn:)];
    UIBarButtonItem *typeButton = 
        [[UIBarButtonItem alloc]
        initWithTitle: @"Type"
        style:UIBarButtonItemStylePlain
        target: self
        action:@selector(changeMapType:)];
    NSArray *buttons = [[NSArray alloc] 
         initWithObjects:zoomButton, typeButton, nil];
    toolBar.items = buttons;
}
First the mapView is configured to show the user location (which appears on the map as a blue translucent ball):
mapView.showsUserLocation = YES;
Next two tool bar button items labeled “Zoom” and “Type” are created and configured to call the zoomIn and changeMapType methods respectively. These button are then placed in an array and the array assigned to the items property of the toolbar object in order to make them visible to the user.

[edit] Changing the MapView Region

When the Zoom button is tapped by the user the map view region needs to be changed so that the user’s current location is set as the center location and the region span needs to be changed to 50 meters (analogous to zooming in to the map region). The code to implement this belongs in the zoomIn method located in the mapSampleViewController.m file:
- (void)zoomIn: (id)sender
{
    MKUserLocation *userLocation = mapView.userLocation;
    MKCoordinateRegion region =
       MKCoordinateRegionMakeWithDistance (
          userLocation.location.coordinate, 50, 50);
    [mapView setRegion:region animated:NO];
}
This method performs some very simple operations in order to achieve the desired effect in the mapView object. Firstly, the user’s current location is ascertained by accessing the userLocation property of the map view object. This is stored in the form of an MKUserLocation object which, in turn, contains the coordinates of the user. Next, the MKCoordinateRegionMakeWithDistance function is called in order to generate an MKCoordinateRegion object consisting of the user’s location coordinates and a span that stretches 50 meters both to the North and South of the current location. Finally, this region object is passed through to the setRegion method of the mapView object.
Now that the Zoom functionality has been implemented it is time to configure the map type switching feature of the application.

[edit] Changing the Map Type

The map type of a map view is controlled by the object’s mapType property. Supported values for this property are MKMapTypeStandard, MKMapTypeSatellite and MKMapTypeHybrid. For the purposes of this example application the map will switch between standard and satellite modes. Within the mapSampleViewController.m file add the changeMapType action method connected to the Type button as follows:
- (void) changeMapType: (id)sender
{
    if (mapView.mapType == MKMapTypeStandard)
        mapView.mapType = MKMapTypeSatellite;
    else
        mapView.mapType = MKMapTypeStandard;
} 
This very simple method simply toggles between the two map types when the button is tapped by the user.

[edit] Testing the iPhone MapView Application

Now that more functionality has been implemented, it is a good time to build and run the application again so click on the Xcode Run button to load the application into the iOS iPhone Simulator. Once the application has loaded, a blue dot should appear over Northern California. Since the application is running in the simulator environment the location information is simulated to match the coordinates of Apple’s headquarters in Cupertino, CA. Select the Type button to display the satellite view and then zoom in to get a better look at the company’s parking lot:


Figure 48-3

To get real location information, load the application onto an iPhone device (details of which can be found in the Testing iOS 5 Apps on the iPhone – Developer Certificates and Provisioning Profiles chapter of this book).

[edit] Updating the Map View based on User Movement

Assuming that you installed the application on a physical iPhone device and went somewhere with the device in your possession you may have noticed that the map did not update as your location changed and that the blue dot marking your current location eventually went off the screen (also assuming, of course, that you had zoomed in).
In order to configure the application so that the map automatically tracks the movements of the user the first step is to make sure the application is notified when the location changes. At the start of this tutorial the view controller was declared as conforming to the MKMapViewDelegate delegate protocol. One of the methods that comprise this protocol is the didUpdateUserLocation method. When implemented, this method is called by the map view object whenever the location of the device changes. We must, therefore, first specify that the mapSampleViewContoller class is the delegate for the mapView object, which can be performed by adding the following line to the viewDidLoad method located in the mapSampleViewController.m file:
mapView.delegate = self; 
The next task involves the implementation of the didUpdateUserLocation method in the mapSampleViewController.m file:
- (void)mapView:(MKMapView *)mapView 
didUpdateUserLocation:
(MKUserLocation *)userLocation
{
    self.mapView.centerCoordinate = 
          userLocation.location.coordinate;
} 
The delegate method is passed as an argument an MKUserLocation object containing the current location coordinates of the user. This value is simply assigned to the center coordinate property of the mapView object such that the current location remains at the center of the region. When the application is now installed and run on a device the current location will no longer move outside the displayed region as the device location changes.

[edit] Adding Basic Annotations to a Map View

The last task in this tutorial is to add an annotation at a specific location on the map view. For the purposes of this example, we will add a standard annotation (represented by default by a red pin) at the coordinates of Microsoft’s headquarters in Redmond, Washington. Although this is a very simple example it is important to keep in mind that annotations may also be used to perform more advanced tasks such as displaying custom images and multiple annotations on a single map.
The annotation in this example will also display a title and subtitle when selected by the user. In order to create a basic annotation it is necessary to create a CLLocationCoordinate2D object containing the coordinates at which the annotation is to appear. An MKPointAnnotation object is then created and assigned the coordinate object, title and subtitle strings. Finally the addAnnotation method of the map view object is called to add the annotation to the map. The code fragment for these steps is as follows:
CLLocationCoordinate2D annotationCoord;
annotationCoord.latitude = 47.640071;
annotationCoord.longitude = -122.129598;
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = annotationCoord;
annotationPoint.title = @"Microsoft";
annotationPoint.subtitle = @"Microsoft's headquarters";
[mapView addAnnotation:annotationPoint]; 
Add this code to the end of the viewDidLoad method and build and run the application. The map should now appear with a red pin located at the designated location. Tapping the pin will display the title and subtitle:


Figure 48-4

Core Location Framework

Getting iPhone Location Information using the iOS 5 Core Location Framework
Having covered the basics of location management in iOS 5 iPhone applications in the previous chapter it is now time to put theory into practice and work step-by-step through an example application. The objective of this chapter is to create a simple iOS application that tracks the latitude, longitude and altitude of an iPhone. In addition the level of location accuracy will be reported, together with the distance between a selected location and the current location of the device.



Contents


















[edit] Creating the Example iOS 5 iPhone Location Project

The first step, as always, is to launch the Xcode environment and start a new project to contain the location application. Once Xcode is running, select the File -> New Project… menu option and configure a new iOS iPhone application named location with a matching class prefix using the Single View Application template.

[edit] Adding the Core Location Framework to the Project

In order to access the location features of the iPhone the Core Location Framework must be included into the project. This can be achieved by selecting the product target entry from the project navigator panel (the top item named location) and clicking on the Build Phases tab in the main panel. In the Link Binary with Libraries section click on the ‘+’ button, select the CoreLocation.framework entry from the resulting panel and click on the Add button.

[edit] Configuring the View Controller

The view controller for our application is going to require a number of outlets that will enable the controller to display location information on the labels we will build into the user interface of the application. In addition an action method needs to be defined to connect to a button that will reset the distance counter when touched by the user. Also required are references to CLLocationManager and CLLocation objects which, in turn, require that the CoreLocation.h file be imported. Bringing all these requirements together gives us a locationViewController.h file that reads as follows:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface locationViewController : UIViewController
        <CLLocationManagerDelegate>
{
        CLLocationManager *locationManager;
        UILabel *latitude;
        UILabel *longitude;
        UILabel *horizontalAccuracy;
        UILabel *altitude;
        UILabel *verticalAccuracy;
        UILabel *distance;
        UIButton *resetButton;
        CLLocation *startLocation;
}
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) IBOutlet UILabel *latitude;
@property (strong, nonatomic) IBOutlet UILabel *longitude;
@property (strong, nonatomic) IBOutlet UILabel *horizontalAccuracy;
@property (strong, nonatomic) IBOutlet UILabel *verticalAccuracy;
@property (strong, nonatomic) IBOutlet UILabel *altitude;
@property (strong, nonatomic) IBOutlet UILabel *distance;
@property (strong, nonatomic) CLLocation *startLocation;
- (IBAction)resetDistance;
@end
Note the inclusion of the <CLLocationManagerDelegate> declaration in the above file. This is required to notify the compiler that the view controller class implements the Location Manager Delegate protocol.
Having declared the outlets, the next step is to design the user interface.

[edit] Designing the User Interface

The user interface for this example location app is going consist of a number of labels (some of which will be connected to the outlets declared in the preceding section) and a button that will be connected to the previously declared resetDistance action method. Initiate the user interface design process by selecting the locationViewController.xib file. Once the view has loaded into the Interface Builder editing environment, create a user interface that resembles as closely as possible the view illustrated in Figure 47-1:

Figure 47-1


In the case of the five labels in the right hand column which will display location and accuracy data, make sure that the labels are stretched to the right until the blue margin guideline appears. The data will be displayed to multiple levels of decimal points requiring space beyond the default size of the label.

Establish a connection between the latitude outlet declared in the view controller and the corresponding user interface label by Ctrl-clicking on the File’s Owner icon and dragging the blue line to the label located to the right of the Latitude label. Release the line and select the latitude outlet from the resulting menu. Repeat this task to establish outlet connections to the remaining six data display labels.
The final step of the user interface design process is to connect the button object to the resetDistance action method. This is achieved by selecting the button in the view window and displaying the Connections Inspector window (View -> Utilities -> Show Connections Inspector). Click in the round circle to the right of the Touch Up Inside event and drag the line to the File’s Owner object. On releasing the mouse button, select the resetDistance method from the resulting menu.

[edit] Creating the CLLocationManager Object

The next task is to implement the code to create an instance of the CLLocationManager class. Since this needs to occur when the application starts up an ideal location is in the view controller’s viewDidLoad method. Whilst making this code change it is also a good opportunity to add the necessary @synthesize directives to the locationViewController.m file:
#import "locationViewController.h"
@implementation locationViewController
@synthesize longitude, latitude, horizontalAccuracy, verticalAccuracy, altitude, distance;
@synthesize locationManager, startLocation;
.
.
.
- (void)viewDidLoad {
    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.delegate = self;
    [locationManager startUpdatingLocation];
    startLocation = nil;
}
The above code creates a new CLLocationManager object instance and configures it to use the “best accuracy” setting. It then declares itself as the application delegate for the object. The location manager object is then instructed to begin updating location information via a call to the startUpdatingLocation method. Since location tracking has just begun at this point, the startLocation object is also set to nil.

[edit] Implementing the Action Method

The button object in the user interface is connected to the resetDistance action method so the next task is to implement that action. All this method needs to do is set the startlocation object to nil:
-(void)resetDistance
{
        startLocation = nil;
}

[edit] Implementing the Application Delegate Methods

When the location manager detects a location change, it calls the didUpdateToLocation delegate method. Since the view controller was declared as the delegate for the location manager in the viewDidLoad method, it is necessary to now implement this method:
#pragma mark -
#pragma mark CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager
   didUpdateToLocation:(CLLocation *)newLocation
                  fromLocation:(CLLocation *)oldLocation
{
     NSString *currentLatitude = [[NSString alloc] 
                  initWithFormat:@"%g", 
                  newLocation.coordinate.latitude];
     latitude.text = currentLatitude;
     NSString *currentLongitude = [[NSString alloc] 
          initWithFormat:@"%g",
          newLocation.coordinate.longitude];
     longitude.text = currentLongitude;
     NSString *currentHorizontalAccuracy = 
              [[NSString alloc] 
             initWithFormat:@"%g",
             newLocation.horizontalAccuracy];
     horizontalAccuracy.text = currentHorizontalAccuracy;
     NSString *currentAltitude = [[NSString alloc] 
                  initWithFormat:@"%g",                                                          
                  newLocation.altitude];
     altitude.text = currentAltitude;
     NSString *currentVerticalAccuracy = 
              [[NSString alloc] 
              initWithFormat:@"%g",
              newLocation.verticalAccuracy];
     verticalAccuracy.text = currentVerticalAccuracy;
     if (startLocation == nil)
            self.startLocation = newLocation;
       
     CLLocationDistance distanceBetween = [newLocation
            distanceFromLocation:startLocation];
     NSString *tripString = [[NSString alloc] 
           initWithFormat:@"%f", 
           distanceBetween];
     distance.text = tripString;
}
Despite the apparent length of the method it actually performs some very simple tasks. To begin with it extracts location and accuracy information from the newLocation CLLocation object passed through to the method as an argument. In each case, it creates an NSString object containing the extracted value and displays it on the corresponding user interface label.
If this is the first time that the method has been called either since the application was launched or the user pressed the Reset Distance button, the locationDistance object is set to the current location. The distanceFromLocation method of the newLocation object is then called passing though the locationDistance object as an argument in order to calculate the distance between the two points. The result is then displayed on the distance label in the user interface.
The didFailWithError delegate method is called when an error is encountered by the location manager instance. This method should also, therefore, be implemented:
-(void)locationManager:(CLLocationManager *)manager 
didFailWithError:(NSError *)error
{
}
The action taken within this method is largely up to the application developer. The method, might, for example, simply display an alert to notify the user of the error.

[edit] Releasing Memory

The final step prior to testing the application is to make sure that any memory allocated during the application lifecycle is released. This is achieved within the viewDidUnload method:
- (void)viewDidUnload {
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
        self.latitude = nil;
        self.longitude = nil;
        self.horizontalAccuracy = nil;
        self.verticalAccuracy = nil;
        self.altitude = nil;
        self.startLocation = nil;
        self.distance = nil;
        self.locationManager = nil;
}

[edit] Building and Running the iPhone Location Application

Click on the Run button located in the Xcode project window toolbar. If any compilation errors are encountered correct those problems and try again. Once the application has compiled and linked it will launch into the iOS Simulator. Before location information can be gathered, the user is prompted to grant permission. Once permission is granted, the application will begin tracking location information. By default, the iOS Simulator will be configured to have no current location causing the labels to remain unchanged. In order to simulate a location, select the iOS Simulator Debug -> Location menu option and select either one of the pre-defined locations or Custom Location… to enter a specific latitude and longitude. The following figure shows the application running in the iOS Simulator after the Apple location has been selected from the menu:


Figure 47-2

To experience the full functionality of the application it will be necessary to install it on a physical iPhone device, a process that is outlined in the chapter entitled Testing iOS 5 Apps on the iPhone – Developer Certificates and Provisioning Profiles. Once the application is running on an iPhone the location data will update as you change location with the device.

One final point to note is that the distance data relates to the distance between two points, not the distance travelled. For example, if the device accompanies the user on a 10 mile trip that returns to the start location the distance will be displayed as 0 (since the start and end points are the same).