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

Monday, 30 July 2012

#12 XCode Project Properties

  • -info.plist (Example : MyGreetings-info.plist)
  • Icon image files = icon1.png (iphone < version 4) size 57 x 57
  • Icon image files = icon@2x.png (iphone >= 4) size 114 x 114

#11 Building Application in XCode

  • Build = Compile (to iOS understandable format) + Link (with necessary frameworks)
  • Command Reference
  • At development stage choose, Active Configuration = "Debug"
  • At release stage choose, Active Configuration = "Release" 


#10 Objective C Method Pattern

  • Example:
- (BOOL) application: (UIApplication *) application didFinishLaunchingWithOptions:(NSDictionary *) launchOptions {
     
}
  • Description:
    • -  (Minus sign) : represents instance method, use + for class method
    • (BOOL) : Method return type
    • application: Method name first part
    • (UIApplication *) : parameter type first part
    • application : parameter variable name
    • didFinishLaunchingWithOptionsMethod name second part
    • (NSDictionary *)  : parameter type first second part
    • launchOptions : parameter variable name second part


#9 Understanding New XCode Project Structure for iOS

--------------------------------------------------------------------------------------------------------------
Learn Japanese with Sound of Kanji (FREE !!!)

Level 5: https://itunes.apple.com/vn/app/sound-of-kanji-5/id930545991?mt=8
Level 4: https://itunes.apple.com/vn/app/sound-of-kanji-4/id931983628?mt=8
--------------------------------------------------------------------------------------------------------------

Thursday, 26 July 2012

# P1: Investment Calculator on iOS

Project Background
Develop an Application to calculate Future Values (Simple Future Value and Compound Future Value) for the given Principal amount, Period in years and rate of interest.
Reference Formulas:
    Simple Future Value = principal + (principal * interest * period);
    Compound Future Value = principal * [ (interest + 1) ^ period ]

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
-----------------------
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITextFieldDelegate> {
    IBOutlet UILabel *i;
    UISlider *slider;
    IBOutlet UILabel *futureValueSimple;
    IBOutlet UILabel *futureValueCompound;
    IBOutlet UITextField *months;
    IBOutlet UITextField *principal;
}

@property (nonatomic, retain) UILabel *i;
@property (nonatomic, retain) UILabel *futureValueSimple;
@property (nonatomic, retain) UILabel *futureValueCompound;
@property (nonatomic, retain) UITextField *months;
@property (nonatomic, retain) UITextField *principal;

-(IBAction)valueChange:(id)sender;
-(IBAction)iChange:(id)sender;
-(void)updateFutureValue;

@end

ViewController.m
-----------------------
#import "ViewController.h"

@implementation ViewController

@synthesize i;
@synthesize futureValueSimple;
@synthesize futureValueCompound;
@synthesize months;
@synthesize principal;

-(IBAction)valueChange:(UIStepper *)sender {
    int m = [sender value];
    
    [months setText : [NSString stringWithFormat:@"%d",m]];
    
    [self updateFutureValue];
}

-(IBAction)iChange:(UISlider*) sender {
    
    double interest = [sender value];
    
    [i setText:[NSString stringWithFormat:@"%.2f", interest]];
    
    [self updateFutureValue];
    
}

//Delegate Method from <UITextFieldDelegate>
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
    //dismiss keyboard    
    [theTextField resignFirstResponder];
    [self updateFutureValue];
    return YES;
}

- (void)updateFutureValue {
    
    float interest =  [[i text] floatValue] / 100.0
    int n =  [[months text] intValue];
    float p =  [[principal text] floatValue];
    
    float fs = p + (p * interest * n);
    float fc = p * pow((interest + 1), n);
    
    //fv = pv(i + 1)^m
    [futureValueSimple setText:[NSString stringWithFormat:@"%.2f", fs]];
    [futureValueCompound setText:[NSString stringWithFormat:@"%.2f", fc]];
    
    return;
}

- (void)dealloc {
    [i release];
    [futureValueSimple release];
    [futureValueCompound release];
    [months release];
    [principal release];
    [super dealloc];
}

ViewController.xib

Connections
  • All Relevant Connections between Code and View
  • Method Connections

































  • Similarly do other UI connections
Output

Monday, 23 July 2012

# UIStepper

------------------------------------------------------------------------------
  • ViewController.h
------------------------------------------------------------------------------
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    IBOutlet UITextField *i;
}

@property (nonatomic, retain) UITextField *i;

-(IBAction)valueChange:(id)sender;

@end
------------------------------------------------------------------------------
  • ViewController.m
------------------------------------------------------------------------------
#import "ViewController.h"

@implementation ViewController

@synthesize i;

-(IBAction)valueChange:(UIStepper *)sender {
 
    double value = [sender value];
 
    [i setText : [NSString stringWithFormat:@"%f",value]];
 
}
------------------------------------------------------------------------------

  • ViewController.xib
------------------------------------------------------------------------------




------------------------------------------------------------------------------

  • Output
------------------------------------------------------------------------------



Sunday, 22 July 2012

#8 iOS Development Environment

  • XCode IDE (Integrated Development Environment)
    • Powerful development environment for creating apps. for Mac, iPhone, and iPad
    • It includes 
      • SDK for Mac OS X and iOS
      • Analysis Tool (Instruments)
      • iOS simulator
      • Interface Builder (IB) is for creating User Interfaces visually and connecting those to underlying implementation. IB exposes UI elements as object, so that their attributes and properties can be modified using visual interfaces. 
  • Download XCode from Apple's developer website https://developer.apple.com/xcode/

Saturday, 21 July 2012

#7 Generating and Installing Development Provisioning Profile for IPhone

  • Prepare necessary IDs which will be required by Provisioning Assistant later
    1. Create Application ID : Unique identifier that IPhone OS can grant access to its keychain (Secure information store area). This ID belongs to one or group of applications.
    2. Get UDDI for your device by connecting it to the Mac and then use XCode menu
        • XCode -> Window -> Organizer
    3. Generate a CSR (Certificate Signing Request) using below steps on Mac,
        • Start -> [/Applications/Utilities/Keychain Access]

        • Use below menu [Request Certificate From a Certificate Authority] to request a certificate


        • Save CSR requests to your Hard Disk
                                       CSR File : MyDevCertificateSigningRequest.certSigningRequest


  • Start provisioning assistant from iOS Developer Center website
    • Click [Launch Assistant] button to start the provisioning process. 

      • Create Application ID

    • Follow steps as per Apple's Provisioning Assistant to finally get below two files
        • mobile provisioning certificate (DevelopmentProvisioningProfile_CapitalQuizApp.mobileprovision)
        • development certificate (ios_development.cer)
    • Exit the process after downloading above two files.
  • Install Development Provisional Profile (.mobileprovision) and development certificate (.cer) will below steps:
      • Install mobile provisioning certificate to XCode
        1. Double Click (.mobileprovision) file
        2. XCode will launch and silently install the profile
        3. Double check with, Xcode -> Window -> Organizer
      • Install development certificate (.cer) in to Key Chain
        1. Double Click (. cer) file
        2. Key chain utility will start and guide to install the .cer file