【问题标题】:Create PDF from UIScrollView (pages after 1st are blank)从 UIScrollView 创建 PDF(第 1 页之后的页面为空白)
【发布时间】:2015-02-10 19:56:23
【问题描述】:

我一直在堆栈上,谷歌试图找到正确的方法来解决这个问题,任何帮助都会很棒。

我可以在 PDF 中呈现第一页,但其他所有页面都是空白的。

我在情节提要的视图控制器上有一个 UIScrollView。我在视图控制器的 viewDidLoad 方法中将内容动态加载到该滚动视图中。添加任何项目后,我记录它的高度,然后相应地设置滚动视图的内容大小高度,因此滚动视图很好。它的内容宽度设置为 612

然后我调用一个函数来创建一个 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)

}

为什么没有呈现超过第一页的数据?我得到了正确的页数,只有第一页有任何数据。谢谢(我是新手,非常感谢您抽出宝贵时间查看)。

【问题讨论】:

    标签: ios swift pdf uiscrollview


    【解决方案1】:

    您应该使用以下函数将 PDF 上下文的转换矩阵 (CTM) 转换为与滚动 UIScrollView 实例相同的量:

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

    那么您对renderInContext 的调用应该会正常运行。

    您可以通过查看以下示例来查看此方法的实际效果,该示例在特定偏移处截取可见区域的屏幕截图并将其保存到图像中:

    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();
    

    另外,您的 if 条件不正确。将else if pageCount &gt; 1 更改为else if pageCount &gt;= 1,这样它就不会跳过第1 页。

    【讨论】:

    • 感谢重播。我把它直接放在 setContentOffset 下面(就像在你的例子中一样) - 但是第二页仍然是空白的。
    • 我刚刚在 XCode 中尝试过,效果很好。你确定你使用的方法正确吗?
    • 我将其添加到问题中以向您展示。我和你说的完全一样。
    • 刚试了你的代码,你的if条件也不正确。 else if pageNumber &gt; 1 应该是 else if pageNumber &gt;= 1。目前,pageNumber = 1 时它什么也不做。除此之外,代码有效。
    • 回答了我自己的问题。如果我们在开始上下文之前添加scrollViewForContent.setContentOffset(CGPointMake(0, 0), animated: false),它解决了我的问题!
    【解决方案2】:

    通常我使用以下代码从我的 UIView 制作 PDF 文件。试试看会有帮助

     // 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();
    

    举例

    -(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;
    }
    

    【讨论】:

    • 我认为这可能是完成我的任务的更好的整体方式。我开始写这个,使用一个带有两个 UIViews 的 xib(一个用于第一页,第二个用于第一页之后的任何页面)。你有什么技巧可以计算出页数的逻辑吗?我的数据都是动态的。
    • 是的,我确实有我在代码中实现的逻辑,给我一些时间,我会帮助你
    • 谢谢。我很难弄清楚这一点。我通过一个数组和每个数组项对 UIView 执行 for 循环。我跟踪垂直偏移和当前内容高度以查看它是否应该生成一个新页面,但它以一个巨大的循环结束。此外,它不考虑可能比 UIView 中的内容高度更长的字符串。
    • 我猜您是从 UIScrollView 以 PDF 格式呈现的。你的 UIScrollView 一定有这么多视图。如果您遍历 UIScrollView 中的视图,那么您将能够将所有视图呈现为 PDF
    • 我不再是了,我把那个解决方案扔掉了。当我试图渲染滚动视图时,不同的东西被切断了,不可能让它看起来不错。我只有两个 UIView,一个是带有一些标题信息的第一页,另一个是带有页码的空白页。
    猜你喜欢
    • 2016-12-11
    • 2014-07-03
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    相关资源
    最近更新 更多