Monday 24 June 2013

Send e-mail in background from iOS Application SMTP gmail account

Method :
1. Import CFNetwork.framework to your project.
2. Include     #import "SKPSMTPMessage.h"
                    #import "NSData+Base64Additions.h" // for Base64 encoding

3. Include <SKPSMTPMessageDelegate> to your ViewController
4.  Download SKPSMTPMessage library from  


5. Drag and Drop "SMTPLibrary" folder you have downloaded to your project.



       Before proceeding, let you know that i am using sender/receiver email address and sender password hardcoded in the code for this example.But, you may grab this credentials from user, allowing them to input in some sort of forms(using UIViews).


-(void) sendEmailInBackground {
            NSLog(@"Start Sending");
            SKPSMTPMessage *emailMessage = [[SKPSMTPMessage alloc] init];
            emailMessage.fromEmail = @"sender@gmail.com"; //sender email address
            emailMessage.toEmail = @"receiver@gmail.com";  //receiver email address
            emailMessage.relayHost = @"smtp.gmail.com";
            //emailMessage.ccEmail =@"your cc address";
           //emailMessage.bccEmail =@"your bcc address";
            emailMessage.requiresAuth = YES;
            emailMessage.login = @"sender@gmail.com"; //sender email address
            emailMessage.pass = @"Passwxxxx"; //sender email password
            emailMessage.subject =@"@"email subject header message";
            emailMessage.wantsSecure = YES; 
            emailMessage.delegate = self; // you must include <SKPSMTPMessageDelegate> to your class
           NSString *messageBody = @"your email body message";
         //for example :   NSString *messageBody = [NSString stringWithFormat:@"Tour Name: %@\nName: %@\nEmail: %@\nContact No: %@\nAddress: %@\nNote: %@",selectedTour,nameField.text,emailField.text,foneField.text,addField.text,txtView.text];
      // Now creating plain text email message
 NSDictionary *plainMsg = [NSDictionary
                        dictionaryWithObjectsAndKeys:@"text/plain",kSKPSMTPPartContentTypeKey,                               
 messageBody,kSKPSMTPPartMessageKey,@"8bit",kSKPSMTPPartContentTransferEncodingKey,nil];
  emailMessage.parts = [NSArray arrayWithObjects:plainMsg,nil];
        
            [emailMessage send];
     // sending email- will take little time to send so its better to use indicator with message showing sending...
}

Now, handling delegate methods :
// On success

-(void)messageSent:(SKPSMTPMessage *)message{

    NSLog(@"delegate - message sent");
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message sent." message:nil delegate:nilcancelButtonTitle:@"Ok" otherButtonTitles: nil];
[alert show]; 
}
// On Failure

-(void)messageFailed:(SKPSMTPMessage *)message error:(NSError *)error{

// open an alert with just an OK button
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error!" message:[error localizedDescription] delegate:nilcancelButtonTitle:@"Ok" otherButtonTitles: nil];
[alert show];
NSLog(@"delegate - error(%d): %@", [error code], [error localizedDescription]);
}


Before you proceed you need to do changes as below:
1. If your project ARC is enabled and library has ARC disabled code  then you can disable your project ARC by going through your project target -> Build Settings ->Objective-c Automatic Reference Counting -> set NO
Or, if you only want to disable ARC for those library files only then  you can do it as :  To disable ARC for source files in Xcode 4, select the project and the target in Xcode. Under the target "Build Phases" tab, expand the Compile Sources build phase, select the library source files(.m file), then press Enter to open an edit field, and type 
-fno-objc-arc as the compiler flag for those files.

2. If you have encountered compiling error like  this in pic :
Then solution is go to your project target -> Build Phases -> Compile Sources -> add your all the .m class of your SMTP library .

That's all.

Happy iCoding

Monday 15 April 2013

Convert Html to pdf in iOS


 In this post we will learn on how to generate a pdf from an html file, or convert an html rendered in a UIWebView into a pdf.
Steps to convert html file to pdf
Step 1: Create a new project, and choose View Based Application from the project template. We will name our project “HtmlToPdfDemo”. 
Step 2:  Then add UIWebView into our HtmlToPdfDemoViewController.xib file. We will now create an outlet for our UIWebView, and write an action as follows:
#import <UIKit/UIKit.h>

@interface HtmlToPdfDemoViewController: UIViewController
{
    UIWebView *webView;
}
@property (nonatomic,retain) IBOutlet UIWebView *webView;

- (IBAction) htmlToPdfButtonPressed:(id)sender;

@end

Step 3:  Our initial project setup is complete, we will get started with pdf generation stuff. I have included a Demo.html file in the bundle, and we will convert this html into a pdf . For this we first load our webView in our viewDidLoad as follows.
- (void)viewDidLoad
{
   [super viewDidLoad];
   NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Demo" ofType:@"html"]];
   NSURLRequest *req = [NSURLRequest requestWithURL:url];
   [webView loadRequest:req];
}
Step 4: Our pdf converting code does not really belong in the HtmlToPdfDemoViewController, so let’s farm that off into a new UIViewController called HTMLtoPDF. Create a new file with the iOS\Cocoa Touch\Objective-C class template, enter HTMLtoPDF for the Class and UIViewController for the subclass,  and finish creating the file. class implements UIWebViewDelegate
    Let’s create a new method in the HTMLtoPDF.m file called createPDFWithHTML: and make it a static method. Also predeclare this method in HTMLtoPDF.h file.
+ (id)createPDFWithHTML:(NSString*)HTML pathForPDF:(NSString*)PDFpath delegate:(id )delegate
               pageSize:(CGSize)pageSize margins:(UIEdgeInsets)pageMargins;
Step 5: Now write one protocol HTMLtoPDFDelegate which extend the protocal to be of type “NSObject” In which we can declare the two methods HTMLtoPDFDidSucceed: and HTMLtoPDFDidFail: These protocol methods will returns the generated pdf file to HtmlToPdfDemoViewController. Following are the code for HTMLtoPDF.h file.
// Declare pdf paper size
#define kPaperSizeA4 CGSizeMake(595,842)
#define kPaperSizeLetter CGSizeMake(612,792)

@protocol NDHTMLtoPDFDelegate 
@optional
- (void)HTMLtoPDFDidSucceed:(NDHTMLtoPDF*)htmlToPDF;
- (void)HTMLtoPDFDidFail:(NDHTMLtoPDF*)htmlToPDF;
@end

@interface NDHTMLtoPDF : UIViewController 
@property (nonatomic, weak) id  delegate;
@property (nonatomic, strong, readonly) NSString *PDFpath;

+ (id)createPDFWithHTML:(NSString*)HTML pathForPDF:(NSString*)PDFpath delegate:(id )delegate pageSize:(CGSize)pageSize margins:(UIEdgeInsets)pageMargins;

@end
To convert html to pdf look at the HTMLtoPDF.m 
#import "NDHTMLtoPDF.h"

@interface UIPrintPageRenderer (PDF)
- (NSData*) printToPDF;
@end

@implementation NDHTMLtoPDF
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.webview = [[UIWebView alloc] initWithFrame:self.view.frame];
    webview.delegate = self;
    [self.view addSubview:webview];
    [webview loadHTMLString:self.HTML baseURL:nil];
}

+ (id)createPDFWithHTML:(NSString*)HTML pathForPDF:(NSString*)PDFpath delegate:(id )delegate
               pageSize:(CGSize)pageSize margins:(UIEdgeInsets)pageMargins
{
    NDHTMLtoPDF *creator = [[NDHTMLtoPDF alloc] initWithHTML:HTML delegate:delegate pathForPDF:PDFpath pageSize:pageSize margins:pageMargins];
    return creator;
}

- (id)initWithHTML:(NSString*)HTML delegate:(id )delegate
        pathForPDF:(NSString*)PDFpath pageSize:(CGSize)pageSize margins:(UIEdgeInsets)pageMargins
{
    self = [super init];
    if (self)
    {
        self.HTML = HTML;
        self.delegate = delegate;
        self.PDFpath = PDFpath;
        self.pageMargins = pageMargins;
        self.pageSize = pageSize;
        
        [[UIApplication sharedApplication].delegate.window addSubview:self.view];
        self.view.frame = CGRectMake(0, 0, 1, 1);
        self.view.alpha = 0.0;
    }
    return self;
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    if (webView.isLoading) return;
    
    UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
    [render addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];
    CGRect printableRect = CGRectMake(self.pageMargins.left,
                                  self.pageMargins.top,
                                  self.pageSize.width - self.pageMargins.left - self.pageMargins.right,
                                  self.pageSize.height - self.pageMargins.top - self.pageMargins.bottom);
   CGRect paperRect = CGRectMake(0, 0, self.pageSize.width, self.pageSize.height);
    
    [render setValue:[NSValue valueWithCGRect:paperRect] forKey:@"paperRect"];
    [render setValue:[NSValue valueWithCGRect:printableRect] forKey:@"printableRect"];

    NSData *pdfData = [render printToPDF];
    [pdfData writeToFile: self.PDFpath  atomically: YES];
    [self terminateWebTask];

    if (self.delegate && [self.delegate respondsToSelector:@selector(HTMLtoPDFDidSucceed:)])
        [self.delegate HTMLtoPDFDidSucceed:self];
    
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    if (webView.isLoading) return;
    [self terminateWebTask];
    if (self.delegate && [self.delegate respondsToSelector:@selector(HTMLtoPDFDidFail:)])
      [self.delegate HTMLtoPDFDidFail:self];
}

- (void)terminateWebTask
{
    [self.webview stopLoading];
    self.webview.delegate = nil;
    [self.webview removeFromSuperview];
    [self.view removeFromSuperview];
    self.webview = nil;
}
@end

@implementation UIPrintPageRenderer (PDF)

- (NSData*) printToPDF
{
    NSMutableData *pdfData = [NSMutableData data];
    
    UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );
        
    [self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)];
    
    CGRect bounds = UIGraphicsGetPDFContextBounds();
        
    for ( int i = 0 ; i < self.numberOfPages ; i++ )
    {
        UIGraphicsBeginPDFPage();
        
        [self drawPageAtIndex: i inRect: bounds];
    }
    UIGraphicsEndPDFContext();
    return pdfData;
}

@end
Step 6: Move to the HtmlToPdfDemoViewController.m  htmlToPdfButtonPressed: method. From that method we have to call createPDFWithHTML: method and pass html, path for storing the pdf file, page size and margins.
- (IBAction)htmlToPdfButtonPressed:(id)sender
{
    NSString *html = [webView      stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];

    self.PDFCreator = [NDHTMLtoPDF createPDFWithHTML:html
                                         pathForPDF:[@"~/Documents/demo.pdf"           stringByExpandingTildeInPath]
                                           delegate:self
                                           pageSize:kPaperSizeLetter
                                            margins:UIEdgeInsetsMake(10, 5, 10, 5)];
}
Step 7:  In HtmlToPdfDemoViewController implements the HTMLtoPDFDelegate methods where you can get pdf file.
- (void)HTMLtoPDFDidSucceed:(NDHTMLtoPDF*)htmlToPDF
{
    NSLog(@"HTMLtoPDF did succeed (%@ / %@)", htmlToPDF, htmlToPDF.PDFpath);
}

- (void)HTMLtoPDFDidFail:(NDHTMLtoPDF*)htmlToPDF
{
    NSLog(@"HTMLtoPDF did fail (%@)", htmlToPDF);
}
Finally generated pdf (demo.pdf)  saves into the documents directory. If you run the app on simulator you can find (demo.pdf) in Documents directory in our Library folder, inside iPhone Simulator.