Fred Faust
Fred Faust

Reputation: 6800

Create PDF from UIScrollView (pages after 1st are blank)

I've been around the block on stack and google trying to get the right way to do this ironed out, any help would be great.

I can render the first page in a PDF but every other page is just blank.

I have a UIScrollView on a view controller in storyboard. I dynamically load content into that scroll view in my view controller's viewDidLoad method. After any item is added I record it's height and then set the content size height of the scroll view accordingly, so the scroll view is fine. It's content width is set to 612

Then I call a function to create a PDF:

func createPDF() {

    let pdfData = NSMutableData()

    let scrollHeigt = scrollViewForContent.contentSize.height

    let rawNumberOfPages = scrollHeigt / CGFloat(792)
    let numberOfPages = Int(ceil(rawNumberOfPages))

    var pageNumber = Int()

    let pageSize = CGSizeMake(612, 792)

    UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil)
    let pdfContext : CGContextRef = UIGraphicsGetCurrentContext()

    do {

        UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, pageSize.width, pageSize.height), nil)

        if pageNumber < 1 {

            scrollViewForContent.layer.renderInContext(pdfContext)

        } else if pageNumber >= 1 {

            let offsetForScroll = CGFloat(pageNumber * 792)

            scrollViewForContent.setContentOffset(CGPointMake(0, offsetForScroll), animated: false)

            CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -offsetForScroll)

            scrollViewForContent.layer.renderInContext(pdfContext)

        }

        pageNumber++

    }
        while pageNumber < numberOfPages

    UIGraphicsEndPDFContext()

    let tempDir = NSTemporaryDirectory()

    let tempDirWithFilename = tempDir.stringByAppendingPathComponent("test1.pdf")

    pdfData.writeToFile(tempDirWithFilename, atomically: true)

    let aURL : NSURL = NSURL(fileURLWithPath: tempDirWithFilename)!

    let objectsToShare : NSArray = [aURL]

    let activityVc = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

    self.presentViewController(activityVc, animated: true, completion: nil)

}

How come the data for anything past the first page isn't being rendered? I get the correct number of pages, only the first page has any of the data. Thank you (I'm new and really appreciate you taking the time to look).

Upvotes: 2

Views: 2063

Answers (2)

Shashi3456643
Shashi3456643

Reputation: 2041

Normally I use following code to make PDF file from my UIView. Try it may be it is helpful

 // Creates a mutable data object for updating with binary data, like a byte array
        NSMutableData *pdfData = [NSMutableData data];
        UIGraphicsBeginPDFContextToData(pdfData, view.bounds, nil);

        //Start your first page
        UIGraphicsBeginPDFPage();
        CGContextRef pdfContext = UIGraphicsGetCurrentContext();

        //Now render view with subviews to PDF
        [view.layer renderInContext:pdfContext];

        // Close PDF Render
         UIGraphicsEndPDFContext();

For Example

-(NSMutableData *)createPDFDatafromUIView:(UIView*)aView
{
    // Creates a mutable data object for updating with binary data, like a byte array
    NSMutableData *pdfData = [NSMutableData data];
    // Points the pdf converter to the mutable data object and to the UIView to be converted
    Markup *markup;
    for(UIView *view in [aView subviews])
    {
        if([view isKindOfClass:[Markup class]])
        {
            markup=(Markup*)view;
            break;
        }
    }

    UIGraphicsBeginPDFContextToData(pdfData, markup.bounds, nil);

    for(UIView *view in [aView subviews])
    {
        if([view isKindOfClass:[Markup class]])
        {
            markup=(Markup*)view;



            UIGraphicsBeginPDFPage();
            CGContextRef pdfContext = UIGraphicsGetCurrentContext();

            // draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
            [markup.layer renderInContext:pdfContext];

        }
    }

    // remove PDF rendering context
    UIGraphicsEndPDFContext();
    return pdfData;
}

Upvotes: 0

Cihan Tek
Cihan Tek

Reputation: 5409

You should translate the transformation matrix (CTM) of the PDF context the same amount you scroll the UIScrollView instance using the function below:

CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -offsetForScroll);

Then your call to renderInContext should function properly.

You can see this method in action by looking at the following example that takes the screenshot of the visible area at a particular offset and saves it into an image:

scrollViewForContent.setContentOffset(CGPoint(x: 0, y: shiftAmount), animated: false)

UIGraphicsBeginImageContextWithOptions(scrollViewForContent.frame.size, true, 0);

CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -scrollViewForContent.contentOffset.y);

scrollViewForContent.layer.renderInContext(UIGraphicsGetCurrentContext())

let img = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

Also, your if conditions are incorrect. Change else if pageCount > 1 to else if pageCount >= 1 so that it doesn't skip the page number 1.

Upvotes: 3

Related Questions