在 Apple TV tvOS 中呈现 PDF

Rendering PDF in Apple TV tvOS

我正在为我的 tvOS 应用添加一个功能,允许查看应用中存储的 PDF。但是,如果没有 UIWebView,我不知道该怎么做。我在其他地方问过问题,并收到 link 苹果公司关于可以使用的 API 的冗长无助的文档,甚至在这里它已被引用(CGPDFPage)但没有真正的指南如何实施。有没有人在 tvOS 上成功地完成了这个,如果是的话,你能帮我开始这个过程吗?

tvOS 文档包含有关 creating, viewing and transforming PDF documents 的部分,因此我认为它包含您需要的功能。

该页面上有很多示例代码,但这里是我在 iOS 上出于相同目的使用的一些代码。它应该可以在 tvOS 上运行,但我没有办法测试它:

func imageForPDF(URL: NSURL, pageNumber: Int, imageWidth: CGFloat) -> UIImage {
    let document = CGPDFDocumentCreateWithURL(URL)
    let page = CGPDFDocumentGetPage(document, pageNumber)
    var pageRect = CGPDFPageGetBoxRect(page, .MediaBox)
    let scale = imageWidth / pageRect.size.width
    pageRect.size = CGSizeMake(pageRect.size.width * scale, pageRect.size.height * scale)
    pageRect.origin = CGPointZero

    UIGraphicsBeginImageContext(pageRect.size)
    let ctx = UIGraphicsGetCurrentContext()
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0) // White background
    CGContextFillRect(ctx, pageRect)
    CGContextSaveGState(ctx)

    // Rotate the PDF so that it’s the right way around
    CGContextTranslateCTM(ctx, 0.0, pageRect.size.height)
    CGContextScaleCTM(ctx, 1.0, -1.0)
    CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(page, .MediaBox, pageRect, 0, true))

    CGContextDrawPDFPage(ctx, page)
    CGContextRestoreGState(ctx)

    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image
}

下面是我在 tvOS 中编写和测试的一些代码。请注意,这是在 Objective-c 中。

我创建了两个函数来完成这项工作,以及一个辅助函数来在 UIScrollView 中显示 PDF 图像。第一个将从 URL 打开 PDF 文档。使用了网络 URL。此示例中也可以使用本地文件。

还有一个从本地文件打开文档的辅助函数。

第二个函数将 PDF 文档渲染到上下文中。我选择通过从中创建图像来显示上下文。还有其他处理上下文的方法。

打开文档相当简单,因此代码中没有相关注释。呈现文档稍微复杂一些,因此有评论解释该功能。

完整的申请如下。

- (CGPDFDocumentRef)openPDFLocal:(NSString *)pdfURL {
    NSURL* NSUrl = [NSURL fileURLWithPath:pdfURL];

    return [self openPDF:NSUrl];
}

- (CGPDFDocumentRef)openPDFURL:(NSString *)pdfURL {
    NSURL* NSUrl= [NSURL URLWithString:pdfURL];

    return [self openPDF:NSUrl];
}

- (CGPDFDocumentRef)openPDF:(NSURL*)NSUrl {
    CFURLRef url = (CFURLRef)CFBridgingRetain(NSUrl);

    CGPDFDocumentRef myDocument;
    myDocument = CGPDFDocumentCreateWithURL(url);
    if (myDocument == NULL) {
        NSLog(@"can't open %@", NSUrl);
        CFRelease (url);
        return nil;
    }
    CFRelease (url);

    if (CGPDFDocumentGetNumberOfPages(myDocument) == 0) {
        CGPDFDocumentRelease(myDocument);
        return nil;
    }

    return myDocument;
}
- (void)drawDocument:(CGPDFDocumentRef)pdfDocument
{
    // Get the total number of pages for the whole PDF document
    int  totalPages= (int)CGPDFDocumentGetNumberOfPages(pdfDocument);
    NSMutableArray *pageImages = [[NSMutableArray alloc] init];

    // Iterate through the pages and add each page image to an array
    for (int i = 1; i <= totalPages; i++) {
        // Get the first page of the PDF document
        CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, i);
        CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);

        // Begin the image context with the page size
        // Also get the grapgics context that we will draw to
        UIGraphicsBeginImageContext(pageRect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();

        // Rotate the page, so it displays correctly
        CGContextTranslateCTM(context, 0.0, pageRect.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, pageRect, 0, true));

        // Draw to the graphics context
        CGContextDrawPDFPage(context, page);

        // Get an image of the graphics context
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [pageImages addObject:image];
    }
    // Set the image of the PDF to the current view
    [self addImagesToScrollView:pageImages];
}

-(void)addImagesToScrollView:(NSMutableArray*)imageArray {
    int heigth = 0;
    for (UIImage *image in imageArray) {
        UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
        imgView.frame=CGRectMake(0, heigth, imgView.frame.size.width, imgView.frame.size.height);
        [_scrollView addSubview:imgView];
        heigth += imgView.frame.size.height;
    }
}

要将它们联系在一起,您可以这样做:

CGPDFDocumentRef pdfDocument = [self openPDFURL:@"http://www.guardiansuk.com/uploads/accreditation/10testing.pdf"];
[self drawDocument:pdfDocument];

请注意,我使用的是可在网络上免费获得的 运行dom PDF。我 运行 遇到了 https URLs 的一些问题,但我确信这可以解决,而且它实际上与 PDF 开头问题无关。

这是@jbg 在swift 5

中的回答

func imageForPDF(URL: NSURL, pageNumber: Int, imageWidth: CGFloat) -> UIImage? {
        guard let document = CGPDFDocument(URL) else { return nil }
        guard let page = document.page(at: pageNumber) else { return nil }
        var pageRect = page.getBoxRect(.mediaBox)
        let scale = imageWidth / pageRect.size.width
        pageRect.size = CGSize(width: pageRect.size.width * scale,
                               height: pageRect.size.height * scale)
        pageRect.origin = CGPoint.zero
        
        UIGraphicsBeginImageContext(pageRect.size)
        guard let context = UIGraphicsGetCurrentContext()  else { return nil }
        context.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        context.fill(pageRect)
        context.saveGState()
        
        // Rotate the PDF so that it’s the right way around
        context.translateBy(x: 0.0, y: pageRect.size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        context.concatenate(page.getDrawingTransform(.mediaBox, rect: pageRect, rotate: 0, preserveAspectRatio: true))
        
        context.drawPDFPage(page)
        context.restoreGState()
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

`