An Example iOS 6 iPhone MKMapItem Application

From Techotopia
Revision as of 20:01, 27 October 2016 by Neil (Talk | contribs) (Text replacement - "<table border="0" cellspacing="0">" to "<table border="0" cellspacing="0" width="100%">")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
PreviousTable of ContentsNext
Integrating Maps into iPhone iOS 6 Applications using MKMapItemGetting iPhone Location Information using the iOS 6 Core Location Framework


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


The objective of this chapter is to work through the creation of an example iOS 6 iPhone application which makes use of reverse geocoding together with the MKPlacemark and MKMapItem classes. The application will consist of a screen into which the user will be required to enter destination address information. When a button is selected by the user, a map will be launched containing turn-by-turn directions from the user’s current location to the specified destination.


Contents


Creating the MapItem Project

Launch Xcode and create a new project by selecting the options to create a new iPhone iOS application based on the Single View Application template. Enter MapItem as the product name and class prefix, set the device menu to iPhone and select the Use Storyboards and Use Automatic Reference Counting options if they are not already selected.

Designing the User Interface

The user interface will consist of four Text Field objects into which the destination address will be entered, together with a Button to launch the map. Select the MainStoryboard.storyboard file in the project navigator panel and, using the Object Library palette, design the user interface layout such that it resembles that of Figure 60-1:


The user interface for an iOS 6 iPhone MKMapKit example

Figure 60-1


If you reside in a country that is not divided into States and Zip code regions, feel free to adjust the user interface accordingly.

The next step is to connect the outlets for the text views and declare an action for the button. Select the Street address Text Field object and display the editor using View -> Assistant Editor -> Show Assistant Editor menu option or the center button of the row of Editor toolbar buttons in the top right hand corner of the main Xcode window.

Ctrl-click on the Street address Text Field object in the view and drag the resulting line to the area immediately beneath the @interface directive in the Assistant Editor panel. Upon releasing the line, the configuration panel will appear. Configure the connection as an Outlet named address and click on the Connect button. Repeat these steps for the City, State and Zip text fields, connecting them to outlets named city, state and zip respectively.

Ctrl-click on the Get Directions button and drag the resulting line to a position beneath the new outlets declared in the Assistant Editor. In the resulting configuration panel, change the Connection type to Action and name the method getDirections. On completion, the MapItemViewController.h file should read as follows:

#import <UIKit/UIKit.h>

@interface MapItemViewController : UIViewController
@property (strong, nonatomic) IBOutlet UITextField *address;
@property (strong, nonatomic) IBOutlet UITextField *city;
@property (strong, nonatomic) IBOutlet UITextField *state;
@property (strong, nonatomic) IBOutlet UITextField *zip;
- (IBAction)getDirections:(id)sender;
@end

Converting the Destination using Forward Geocoding

When the user touches the button in the user interface the getDirections: method will be able to extract the address information from the text fields. The objective will be to create an MKPlacemark object to contain this location. As outlined in Integrating Maps into iPhone iOS 6 Application using MKMapItem, an MKPlacemark instance requires the longitude and latitude of an address before it can be instantiated. The first step in the getDirections: method is to perform a forward geocode translation of the address. Before doing so, however, it is necessary to declare a property in the MapItemViewController.h file in which to store these coordinates once they have been calculated. This will, in turn, require that the <CoreLocation/CoreLocation.h> file be imported. Now is also an opportune time to import the <MapKit/MapKit.h> and <AddressBook/AddressBook.h> files, both of which will be required later in the chapter:

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import <AddressBook/AddressBook.h>

@interface MapItemViewController : UIViewController
@property (strong, nonatomic) IBOutlet UITextField *address;
@property (strong, nonatomic) IBOutlet UITextField *city;
@property (strong, nonatomic) IBOutlet UITextField *state;
@property (strong, nonatomic) IBOutlet UITextField *zip;
- (IBAction)getDirections:(id)sender;
@property CLLocationCoordinate2D coords;
@end

Next, select the MapItemViewController.m file, locate the getDirections: method stub and modify it to convert the address string to geographical coordinates:

- (IBAction)getDirections:(id)sender {
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    NSString *addressString = [NSString stringWithFormat:@"%@ %@ %@ %@",
                               ¬_address.text,
                               _city.text,
                               _state.text,
                               _zip.text];

    [geocoder geocodeAddressString:addressString
                 completionHandler:^(NSArray *placemarks, NSError *error) {

                     if (error) {
                         NSLog(@"Geocode failed with error: %@", error);
                         return;
                     }

                     if (placemarks && placemarks.count > 0)
                     {
                         CLPlacemark *placemark = placemarks[0];

                         CLLocation *location = placemark.location;
                         _coords = location.coordinate;
                         _coords = location.coordinate;

                         [self showMap];
                     }
                 }];
}

The steps used to perform the geocoding translation mirror those outlined in Integrating Maps into iPhone iOS 6 Application using MKMapItem with one difference in that a method named showMap: is called in the event that a successful translation took place. All that remains, therefore, is to implement this method.

Launching the Map

With the address string and coordinates obtained, the final task is to implement the showMap: method. This method will create a new MKPlacemark instance for the destination address, configure options for the map to request driving directions and then launch the map. Since the map will be launched with a single mapItem, it will default to providing directions from the current location. With the MapItemViewController.m file still selected, add the code for the showMap: method so that it reads as follows:

-(void)showMap
{
    NSDictionary *address = @{
      (NSString *)kABPersonAddressStreetKey: _address.text,
      (NSString *)kABPersonAddressCityKey: _city.text,
      (NSString *)kABPersonAddressStateKey: _state.text,
      (NSString *)kABPersonAddressZIPKey: _zip.text
    };

    MKPlacemark *place = [[MKPlacemark alloc] 
           initWithCoordinate:_coords 
           addressDictionary:address];

    MKMapItem *mapItem = [[MKMapItem alloc]initWithPlacemark:place];

    NSDictionary *options = @{
        MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving
    };

    [mapItem openInMapsWithLaunchOptions:options];
}

The method simply creates an NSDictionary containing the AddressBook keys and values for the destination address and then creates an MKPlacemark instance using the address dictionary and the coordinates from the forward-geocoding operation. A new MKMapItem object is created using the placemarker object before another dictionary is created and configured to request driving directions. Finally, the map is launched.

Adding Build Libraries

Before the application can be successfully compiled, some libraries need to be added to the build phases. Within the project navigator panel, select the MapItem target at the top of the list and in the main panel select the Build Phases tab. In the Link Binary with Libraries category, click on the + button and in the resulting list of libraries search for, select and add the CoreLocation.framework library. Repeat this step to also add the MapKit.framework and AddressBook.framework libraries.

Building and Running the Application

Within the Xcode toolbar, click on the Run button to compile and run the application, either on a physical iPhone device or the iOS Simulator. Once loaded, enter an address into the text fields before touching the Get Directions button. The map should subsequently appear together with route between your current location and the destination address. Note that if the app is running in the simulator, the current location will likely default to Apple’s headquarters in California.


An iOS 6 iPhone MKMapItem example app running

Figure 60-2

Summary

The goal of this chapter has been to work through the creation of a simple application designed to use a combination of geocoding and the MKPlacemark and MKMapItem classes. The example application created in this chapter has demonstrated the ease with which maps and directions can be integrated into iOS 6 applications for the iPhone.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
Integrating Maps into iPhone iOS 6 Applications using MKMapItemGetting iPhone Location Information using the iOS 6 Core Location Framework