Thursday, 2 August 2012

#P2 Navigation and Send email using existing Contact Information

Project Background
Develop an application to get Map location and send email based on the Contact information.

Project Framework and other dependencies
- MapKit (Embeds Google Map)
- CoreLocation (get location based on latitude and longitude)
- MessageUI (For email functionality)
- AddressBook and AddressBookUI (To access contact information)
- XCode adds three frameworks by default for View Based project (UIKit, Foundation, CoreGraphics)
- Google URL to get latitude and longitude based on Zip code and other address information
It could return results in CSV format of 4 elements, in which 2nd and 3rd elements are latitude and longitude respectively.
NSString *qUrl = [[NSString alloc] initWithFormat : @"http://maps.google.com/maps/geo?output=csv&q=%@", zipCode];

//CSV format
NSString *qResults = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString: qUrl] encoding: NSUTF8StringEncoding error:nil];

Latitude and Longitude
Latitude : horizontal lines starts from Equator (North and South) Min, Sec , e.g. 45 Deg N
Longitude : vertical lines starts from Green Meridian (East and West) Min, Sec , e.g. 45 E
The longitude line goes from north pole to south pole.

Project Setup
  • Create View Based Project
  • XCode will create necessary ViewController header (.h), implementation (.m) and View (.xib) files.

  • Update above .h and .m files with below code 
ViewController.h
-----------------------
//
//  ViewController.h
//  MyTomo
//
//  Created by santosh on 8/2/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <AddressBook/AddressBook.h> //by default available
#import <AddressBookUI/AddressBookUI.h>
#import <CoreLocation/CoreLocation.h>
#import <MessageUI/MessageUI.h>

@interface ViewController : UIViewController <ABPeoplePickerNavigationControllerDelegate, MFMailComposeViewControllerDelegate> {
    IBOutlet UILabel *name;
    IBOutlet UILabel *email;
    IBOutlet UILabel *zip;
    IBOutlet UIImageView *photo;
    IBOutlet MKMapView *map;
    MKPlacemark *zipAnnotation;// not outlet , no change, hence no property and synthesize
}

@property (nonatomic, retain) UILabel *name;
@property (nonatomic, retain) UILabel *email;
@property (nonatomic, retain) UILabel *zip;
@property (nonatomic, retain) UIImageView *photo;
@property (nonatomic, retain) MKMapView *map;

-(IBAction)getContactInfo:(id)sender;
-(IBAction)sendEMail:(id)sender;

@end

ViewController.m
-----------------------
//
//  ViewController.m
//  MyTomo
//
//  Created by santosh on 8/2/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "ViewController.h"

@implementation ViewController

@synthesize name;
@synthesize email;
@synthesize zip;
@synthesize photo;
@synthesize map;

- (void) createMap: (NSString *)zipCode showAddress:(NSDictionary *) address {
    NSString *qUrl;
    NSString *qResults;
    NSArray *qData;
    
    double latitude;
    double longitude;
    
    MKCoordinateRegion mapRegion; //structure
    
    //send Zip code to Goole to get results in CSV format containing latitude and longitude at 2nd and 3rd place
    //latitude = horizontal line starts from Equator (North and South) Min, Sec , e.g. 45 Deg N
    //longitude = vertical lines starts from Green Meridian (East and West) Min, Sec , e.g. 45 E
    //The longitude line goes from north pole to south pole
    
    qUrl = [[NSString alloc] initWithFormat : @"http://maps.google.com/maps/geo?output=csv&q=%@", zipCode];
    
    //CSV format
    qResults = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString: qUrl] 
                                           encoding: NSUTF8StringEncoding 
                                             error:nil];
    //Break CSV record into Array 
    qData = [qResults componentsSeparatedByString:@","];
    
    if ([qData count] == 4) {
        latitude = [[qData objectAtIndex:2] doubleValue];
        longitude = [[qData objectAtIndex:3] doubleValue];
        
        //Create location coordinate in 2D
        mapRegion.center.latitude = latitude;
        mapRegion.center.longitude = longitude;
        
        [map setRegion:mapRegion animated:YES];
        
        //remove existing annotaion if any
        if (zipAnnotation != nil) {
            [map removeAnnotation:zipAnnotation];
        }
        
        //create annotation
        zipAnnotation = [[MKPlacemark alloc] initWithCoordinate:mapRegion.center addressDictionary:address];
        [map addAnnotation:zipAnnotation];
        [zipAnnotation release];
    }
    
    [qUrl release];
    [qResults release];
    
}

//ABPeoplePickerNavigationControllerDelegate method will show details after clicking on person name !
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    return YES;
}

//ABPeoplePickerNavigationControllerDelegate method
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
    [self dismissModalViewControllerAnimated:YES];
}

//ABPeoplePickerNavigationControllerDelegate method
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person 
                              property:(ABPropertyID)property 
                            identifier:(ABMultiValueIdentifier)identifier {
    
    //Name
    NSString *tomoName;
    tomoName = (NSString *) ABRecordCopyValue(person, kABPersonFirstNameProperty);
    name.text = tomoName;
    [tomoName release];
    
    //Email
    NSString *tomoEmail;
    ABMultiValueRef emailAddresses = ABRecordCopyValue(person, kABPersonEmailProperty);
    tomoEmail = (NSString *) ABMultiValueCopyValueAtIndex(emailAddresses, 0);
    email.text = tomoEmail;
    [tomoEmail release];
    
    //Address
    ABMultiValueRef streetAddresses = ABRecordCopyValue(person, kABPersonAddressProperty);
    
    NSDictionary* firstAddress;
    
    if(ABMultiValueGetCount(streetAddresses) > 0) {
        firstAddress = (NSDictionary *) ABMultiValueCopyValueAtIndex(streetAddresses, 0); 
        //NSString *street = [firstAddress objectForKey:@"Street"];
        //NSString *city = [firstAddress objectForKey:@"City"];
        //NSString *country = [firstAddress objectForKey:@"Country"];
        
        zip.text = [firstAddress objectForKey:@"ZIP"];
        
        [self dismissModalViewControllerAnimated:YES];
        
        [self createMap:zip.text showAddress:firstAddress];
        
    } else {
        //show alert dialog
        UIAlertView *alert = [[UIAlertView alloc]
                              initWithTitle:@"No Address" 
                              message:@"Address not found in contact info."
                              delegate:nil 
                              cancelButtonTitle:@"OK" 
                              otherButtonTitles:nil];
        [alert show];
        [alert release];
        
        zip.text = @"";
        
        [self dismissModalViewControllerAnimated:YES];
         
    }
    
    //photo
    if(ABPersonHasImageData(person)) {
        photo.image = [UIImage imageWithData:(NSData  *) ABPersonCopyImageData(person)];
    }
    
    return NO;
}

-(IBAction)getContactInfo:(id)sender {
    ABPeoplePickerNavigationController *picker;
    
    picker = [[ABPeoplePickerNavigationController alloc] init];
    picker.peoplePickerDelegate = self;
    
    [self presentModalViewController:picker animated:YES];
     
    [picker release];
}

-(IBAction)sendEMail:(id)sender {
    MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
    
    NSArray *emailAddresses = [[NSArray alloc] initWithObjects: email.text, nil];
    
    mailController.mailComposeDelegate = self;
    [mailController setToRecipients: emailAddresses];
    
    [self presentModalViewController:mailController animated:YES];
    
    [mailController release];
    [emailAddresses release];
    
}

//MFMailComposeViewControllerDelegate protocol
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0) {
    [self dismissModalViewControllerAnimated:YES];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

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

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

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}

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

-(void) dealloc {
    [name release];
    [email release];
    [zip release]; 
    [photo release];
    [map release];    
}

@end

ViewController.xib


Connections
  • All Relevant Connections between Code and View

  • Method Connections


















  • Similarly do other UI connections
Output

No comments:

Post a Comment