iOS:将UITableView渲染为PDF

时间:2013-07-21 10:00:08

标签: ios ipad uitableview pdf-generation core-graphics

我编写了pdfGenerator类来渲染整个UITableView以生成PDF。

用法:

[pdfGenerator createPDFFromTableview:self.tableView];

班级方法:

- (void)createPDFFromTableview:(UITableView *)tableview {
    [tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
    [self renderTableView:tableview];

    int rows = [tableview numberOfRowsInSection:0];
    int numberofRowsInView = 17;
    for (int i = 0; i < rows/numberofRowsInView; i++) {
        [tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(i+1)*numberofRowsInView inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
        [self renderTableView:tableview];
    }
}

- (void)renderTableView:(UITableView*)tableview {
    UIGraphicsBeginImageContext(tableview.frame.size);
    [tableview.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *tableviewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIGraphicsBeginPDFPage();
    [tableviewImage drawInRect:tableview.frame];
}

此代码正确滚动tableview,但它仅为第一页创建PDF,而其余页面空白!我不知道它为什么会发生,而它应该按原样获取当前的uitableview快照并呈现但它似乎只对第一页这样做。有人能指出这里可能出现的问题吗?做我想要达到的目标有没有更好的方法?

[编辑]

以下给出相同的结果;

int totalRows = [tableview numberOfRowsInSection:0];
int totalVisibleRows = 17;
for (int i = 0; i < ceil((float)totalRows/totalVisibleRows); i++) {
    [tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:i * totalVisibleRows inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

    [pdfGenerator renderTableView:tableview indexPathStart:[NSIndexPath indexPathForRow:i * totalVisibleRows inSection:0] indexPathEnd:[[tableview indexPathsForVisibleRows] lastObject]];
}

- (void)renderTableView:(UITableView*)tableview indexPathStart:(NSIndexPath *)startingIndexPath indexPathEnd:(NSIndexPath *)endIndexPath {
    CGRect rectToDraw = CGRectUnion([tableview rectForRowAtIndexPath:startingIndexPath], [tableview rectForRowAtIndexPath:endIndexPath]);

    NSLog(@"%@", NSStringFromCGRect(rectToDraw));

    UIGraphicsBeginImageContext(rectToDraw.size);
    [tableview.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *tableviewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIGraphicsBeginPDFPage();
    [tableviewImage drawInRect:rectToDraw];
}

输出rectToDraw:

{{0, 0}, {768, 720}}
{{0, 680}, {768, 720}}
{{0, 1360}, {768, 720}}
{{0, 2040}, {768, 360}}

2 个答案:

答案 0 :(得分:2)

在以编程方式滚动tableview之后,我最终渲染了持有tableview的视图。滚动后渲染tableview似乎不起作用!

答案 1 :(得分:0)

您的图形上下文使用UITableView的框架初始化,因此它始终会查看“第一页”。以下“页面”的图形上下文需要UIScrollView的内部UITableView的上下文偏移量。除非直接访问UIScrollView,否则我建议您使用[UITableView rectForRowAtIndexPath:]方法获取要在步骤(即页面)中绘制的第一行和最后一行的CGRect,并CGRectUnion获取它们一个包含两者的矩形(以及它们之间的所有行)。

修改(根据评论中的要求): 你基本上用这样的东西替换循环中的渲染消息

[self renderTableView:tableview
       indexPathStart:[NSIndexPath indexPathForRow:row inSection:0]
         indexPathEnd:[[tableview indexPathsForVisibleRows] lastObject]];

然后你的渲染方法如下:

- (void)renderTableView:(UITableView*)tableview indexPathStart:(NSIndexPath *)startingIndexPath indexPathEnd:(NSIndexPath *)endIndexPath{
    CGRect rectToDraw = CGRectUnion([tableview rectForRowAtIndexPath:startingIndexPath], [tableview rectForRowAtIndexPath:endIndexPath]);
    NSLog(@"%@", NSStringFromCGRect(rectToDraw));
   //...
}

关于indexPaths的问题。 indexPath.row不会总是0-16。它们将是0-16,17-34,35-51等。这也反映在你的上下文中,即你想为相关的indexPath矩形绘制rect,因为这是支持{的层的'place' {1}}具有当前渲染图形的后备存储。不知道你的PDF绘图程序,你可能还需要检查你的绘图矩形。