Reputation: 1990
I want to Make PDF with Dynamic Content,like text will be dynamic,images will be dynamic so depends on content of course pages wil be dynamic as well,I have followed this tutorial http://code.tutsplus.com/tutorials/generating-pdf-documents--mobile-11265
but in this tutorial content is not dynamic.
Upvotes: 3
Views: 9947
Reputation: 437372
I know this is an old question, but nowadays you would use PDFKit.
In Objective-C:
@import PDFKit;
And then:
PDFDocument *doc = [[PDFDocument alloc] init];
PDFPage *page = [[PDFPage alloc] init];
[doc insertPage:page atIndex:0];
CGRect bounds = [page boundsForBox:kPDFDisplayBoxMediaBox];
PDFAnnotation *textField = [[PDFAnnotation alloc] initWithBounds:bounds forType:PDFAnnotationSubtypeWidget withProperties:nil];
textField.widgetFieldType = PDFAnnotationWidgetSubtypeText;
textField.fontColor = UIColor.whiteColor;
textField.backgroundColor = UIColor.blueColor;
textField.font = [UIFont systemFontOfSize:14];
textField.widgetStringValue = @"WWDC 2017";
[page addAnnotation:textField];
NSURL *fileURL = [[[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:true error:nil] URLByAppendingPathComponent:@"test.pdf"];
if (![doc writeToURL:fileURL]) {
NSLog(@"save failed");
}
Or, in Swift:
import PDFKit
And:
let doc = PDFDocument()
let page = PDFPage()
doc.insert(page, at: 0)
let bounds = page.bounds(for: .mediaBox)
let textField = PDFAnnotation(bounds: bounds, forType: .widget, withProperties: nil)
textField.widgetFieldType = .text
textField.fontColor = .white
textField.backgroundColor = .blue
textField.font = .systemFont(ofSize: 14.0)
textField.widgetStringValue = "WWDC 2017"
page.addAnnotation(textField)
let fileURL = try! FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("test.pdf")
if !doc.write(to: fileURL) {
print("save failed")
}
See Introducing PDFKit on iOS, from which the above the following snippet was taken.
Upvotes: 2
Reputation: 1319
Make some custom methods and use them as per your requirement. Here are some examples,
// Create a method to draw Line of any size anywhere in the pdf,
- (void) drawLine:(CGFloat)ofWidth fromPoint:(CGPoint)from toPoint(CGPoint)to withColor:(UIColor *)color {
//Get Current Graphics Context as a CGContextRef That Provides Graphic Environment for drawing in Quartz 2D
CGContextRef currentContext = UIGraphicsGetCurrentContext();
//Sets the width of line we going to draw.
CGContextSetLineWidth(currentContext, ofWidth);
//Sets the strok color of context
CGContextSetStrokeColorWithColor(currentContext, color.CGColor);
//Starting point of line as X,Y Value
CGPoint startPoint = from;
//Starting point of line as X,Y Value
CGPoint endPoint = to;
//Creates new empty path in given graphic context
CGContextBeginPath(currentContext);
//Begin a new subpath at given points
CGContextMoveToPoint(currentContext, startPoint.x, startPoint.y);
//Append line from the current points to the given points as parameter
CGContextAddLineToPoint(currentContext, endPoint.x, endPoint.y);
//Terminates the subpath of the context
CGContextClosePath(currentContext);
//Draw the corrunt path using drawing mode as paramete.
CGContextDrawPath(currentContext, kCGPathFillStroke);
}
Here is method to put text of any size, any color and any font anywhere,
- (void) drawText:(NSString *)text ofColor:(CGFloat)red Green:(CGFloat)green Blue:(CGFloat)blue withAlpha:(CGFloat)alpha withFont:(UIFont *)font atPoint:(CGRect)Point havingTextAlignment:(UITextAlignment)textAlignment{
//Get Current Graphics Context as a CGContextRef That Provides Graphic Environment for drawing in Quartz 2D
CGContextRef currentContext = UIGraphicsGetCurrentContext();
//Fill the current context with the color.
CGContextSetRGBFillColor(currentContext,red,green,blue,alpha);
//String to Draw
NSString *textToDraw = text;
[textToDraw drawInRect:Point
withFont:font
lineBreakMode:UILineBreakModeWordWrap
alignment:textAlignment];
}
Same will go for image,
- (void) drawImage:(UIImage *)image atFrame:(CGRect)frame {
[image drawInRect:frame];
}
Now you can create a pdf of any type using these methods,
- (void) generatePdfWithFilePath: (NSString *)thefilePath ofData:(NSDictionary *)data andPageSize:(CGSize) pageSize{
UIGraphicsBeginPDFContextToFile(thefilePath, CGRectZero, nil);
// For exampl
[self drawLine:65.0 fromPoint: CGPointMake( 10, 50) toPoint:CGPointMake(pageSize.width - 100) withColor:[UIColor colorWithRed:239.0/255.0 green:239.0/255.0 blue:239.0/255.0 alpha:1.0]];
[self drawText:@"Testing text" ofColor:0.0 Green:0.0 Blue:0.0 withAlpha:1.0 withFont:[UIFont systemFontOfSize:16.0] atPoint:CGRectMake(60,200, pageSize.width - 200,30.0) havingTextAlignment:UITextAlignmentLeft];
UIGraphicsEndPDFContext();
}
Further you can get help from following,
http://www.raywenderlich.com/6581/how-to-create-a-pdf-with-quartz-2d-in-ios-5-tutorial-part-1
http://www.raywenderlich.com/6818/how-to-create-a-pdf-with-quartz-2d-in-ios-5-tutorial-part-2
Upvotes: 0
Reputation: 183
I have also used the same its working fine Hope this will be helpful for you.
Create a block:-
typedef void (^PdfCompletion)(BOOL status, NSString *filePath, NSArray *fbArr);
-(void)addData
{
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
NSMutableDictionary *contactDict = [[NSMutableDictionary alloc] init];
[contactDict setObject:contactTextField.text forKey:@"phonenumber"];
[contactDict setObject:emailTextField.text forKey:@"emailid"];
[contactDict setObject:userNameLabel.text forKey:@"displayname"];
[self drawPdf:contactDict completion:^(BOOL status,NSString *filePath,NSArray *fbArr)
{
if (status)
{
NSMutableArray *arr;
arr = [[NSMutableArray alloc] init];
NSData *filedata;
filedata = [NSData dataWithContentsOfFile:filePath];
double locaTotalFileSize = filedata.length +498;
totalFileSize += locaTotalFileSize;
NSMutableDictionary *fileDict = [[NSMutableDictionary alloc] init];
[fileDict setObject:userPicImageView.image forKey:@"image"];
[fileDict setObject:filePath forKey:@"filePath"];
[fileDict setObject:@"txt" forKey:@"fileType"];
[fileDict setObject:[NSString stringWithFormat:@"%@_%@_%@",@"contact",[self getFbID],[self CurrentSystemTime]] forKey:@"fileName"];
[fileDict setObject:@"1" forKey:@"uploadStatus"];
[fileDict setObject:@"0 KB/0 KB" forKey:@"fileSizeStatus"];
[fileDict setObject:@"0 KB/0 KB" forKey:@"ContentSize"];
[arr addObject:fileDict];
[self switchToReviewFiles:arr];
//////NSLog(@"pdf convrt successfull");
}
else
{
//////NSLog(@"Error to convert into pdf");
}
}];
}
// Then Call The DrawPDF Method::--
-(void)drawPdf:(NSMutableDictionary *)drawText completion:(PdfCompletion)callback
{
NSString* fileName = @"contact_card.txt";
NSArray *arrayPaths =
NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = [arrayPaths objectAtIndex:0];
NSString* txtFileName = [path stringByAppendingPathComponent:fileName];
NSData *data = [NSJSONSerialization dataWithJSONObject:drawText options:NSJSONWritingPrettyPrinted error:nil];
[data writeToFile:txtFileName atomically:YES];
callback(YES, txtFileName, nil);
Upvotes: 2
Reputation: 4728
the easiest way to handle this, like any print job in Cocoa or Cocoa-Touch, is to first make a UIView (or UIViewController) subclass to draw/layout your data as you want it printed. You should do this even if you don't intend to ever show this view on the screen in your finished app. (you still might put it on the screen in development in order to get it looking how you want it.. ) A very simple approach for a model of unknown size might be a UITableViewController. Use Autolayout or the old UIViewAutoResizingMasks so that this view will cope with resizing gracefully. Of course if it is a UIViewController subclass then you could do it with interface builder too..
Once you're in this position drawing to a PDF is trivial
-(BOOL )writePDFtoPath:(NSString *)filePath{
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil);
//note that because I've passed in CGRectZero for the size the context //comes in its default size
/*
default pdf..
8.5 X 11 inch
612 x 792
*/
//this is only 72dpi, but its the default. I have a trick where I zoom
// out before drawing to improve resolution:
NSInteger numberPages = 3; //work out how many pages you need
for (NSInteger page = 0 : page < numberPages : page ++ ){
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
CGFloat scaleFactor = 3.0;
CGContextSaveGState(pdfContext);
CGContextScaleCTM(pdfContext, 1.0/scaleFactor, 1.0/scaleFactor);
///
/// context size is now (612.0 * 3.0 , 792.0 * 3.0) , i.e. resolution 72.0 * 3.0 dpi..
[self.pdfGeneratingView setFrame: CGRectMake( 0.0, 0.0, 612.0*scaleFactor, 792.0*scaleFactor) ]; //let autolayout make it fit
//prepare your view for this page
[self.pdfGeneratingView.layer renderInContext:pdfContext];
CGContextRestoreGState(pdfContext);
}//page drawing loop
BOOL success = [pdfData writeToFile:filePath atomically:YES];
return success;
}
Upvotes: 2
Reputation: 1741
You can pass value using javaScript like this for your dynamic value
Suppose you have a key "myKey" in your HTML
<td><span class="fieldVal" id="myKey"></span></td>
And Pass value using like this
NSBundle *bundle = [NSBundle mainBundle];
NSURL *indexFileURL = [bundle URLForResource:@"name_of_your_local_html" withExtension:@"html"];
[wbView loadRequest:[NSURLRequest requestWithURL:indexFileURL]];
[wbView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"document.getElementById('myKey').innerHTML='%@'",@"myValue"]];
Now for converting HTML to PDF you can use this class
https://github.com/iclems/iOS-htmltopdf/blob/master/NDHTMLtoPDF.h
Upvotes: 2