iOS PDFKit 開發(fā)指北

前言

2017年夏天,在蘋果全球開發(fā)者大會(WWDC)上,蘋果公司終于推出了針對于 iOS 的 PDFKit 支持。PDFKit 自從 MacOS 10.4 以來一直在 AppKit for MacOS 中。但 UIKit 卻遲遲得不到支持,盡管蘋果公司之前在 iBooks 和 Mail 中使用過 PDFKit , 但是該框架并未向開發(fā)人員開房。

PDFKit 包含了大量關(guān)于 PDF 相關(guān)的功能,例如,打開,修改,繪圖和保存 PDF ,也包含了搜索文本。在 iOS 11 后,蘋果終于開放了 PDFKit 。目前(雖然離 PDFKit 發(fā)布已經(jīng)過了一年多),但是目前中文資料和 Demo 確實比較少,下面筆者就帶著大家簡單的了解一下 PDFKit。

image

核心功能

主要核心功能如下:

PDFView

  • 用于顯示 PDF ,包括選擇的內(nèi)容,導(dǎo)航,縮放等功能。

PDFDocument

  • 表示允許您寫入、搜索和選擇PDF數(shù)據(jù)的PDF數(shù)據(jù)或文件。

PDFPage

  • 呈現(xiàn)PDF數(shù)據(jù),添加注釋,獲取頁面文本等等。

PDFAnnotation

  • PDF 中的附加內(nèi)容,包括注釋、鏈接、表單等。

實現(xiàn)一個簡單的 PDF 閱讀器

讓我看到你們的雙手, put your hands up!

創(chuàng)建 PDFView

引入 #import <PDFKit/PDFKit.h> ,創(chuàng)建 PDFView ,創(chuàng)建之前,首先要創(chuàng)建 PDFDocument ,這里通過文件路徑 URl 進行創(chuàng)建。

    NSString *pdfPath = [[NSBundle mainBundle] pathForResource:@"swift" ofType:@"pdf"];
    NSURL *pdfUrl = [NSURL fileURLWithPath:pdfPath];
    PDFDocument *docunment = [[PDFDocument alloc] initWithURL:pdfUrl];

創(chuàng)建 PDFView ,將 PDFDucument 對象賦給 PDFView。

    self.pdfView = [[PDFView alloc] initWithFrame:self.view.bounds];
    self.pdfView.document = docunment;
    self.pdfView.autoScales = YES;
    self.pdfView.userInteractionEnabled = YES;
    self.pdfView.backgroundColor = [UIColor grayColor];

至此,就實現(xiàn)了 PDF 的讀取及顯示。

image

創(chuàng)建 PDFThumbnail

  • PDF 縮略圖的創(chuàng)建

首先獲取 PDFDocument 的屬性 PDFPage :

// Returns a PDFPage object representing the page at index. Will raise an exception if index is out of bounds. Indices
// are zero-based.
- (nullable PDFPage *)pageAtIndex:(NSUInteger)index;

通過 PDFPage 的對象方法,可以獲取 PDF 的縮略圖,這里需傳入圖片的 size:

// Convenience function that returns an image of this page, with annotations, that fits the given size.
// Note that the produced image is "size to fit": it retains the original page geometry. The size you give
// may not match the size of the returned image, but the returned image is guaranteed to be equal or less.
- (PDFKitPlatformImage *)thumbnailOfSize:(PDFSize)size forBox:(PDFDisplayBox)box PDFKIT_AVAILABLE(10_13, 11_0);

創(chuàng)建 collectionViewCell ,通過 collectionView 就可以實現(xiàn)一個大致的功能。

image

點擊跳轉(zhuǎn)

獲取 cell 的點擊事件,取出所點擊的 PDFPage 對象,用下述方法進行跳轉(zhuǎn):

// Scrolls to page.
- (void)goToPage:(PDFPage *)page;

獲取 PDF 的大綱 PDFOutline

PDFOutline 是一個層級關(guān)系的對象,他表示 PDF 的大綱(也就是我們常用的書簽)。每個 PDFOutline 對象都可通過 childAtIndex: 方法獲取出他的孩子對象,注意,這里需要先判斷 numberOfChildren,以確定該 outline 對象存在多少個孩子節(jié)點,避免下標(biāo)超界引發(fā)的崩潰。

實現(xiàn)大綱功能

從 PDFDocument 中獲取 PDFOutline

PDFOutline *outline = self.document.outlineRoot;

遍歷 outline 孩子節(jié)點(默認(rèn)只遍歷一層)

- (void)setOutlineRoot:(PDFOutline *)outlineRoot
{
    _outlineRoot = outlineRoot;
    
    for (int i = 0; i < outlineRoot.numberOfChildren; i++)
    {
        PDFOutline *outline = [outlineRoot childAtIndex:i];
        outline.isOpen = NO;
        [self.arrData addObject:outline];
    }
    
    [self.tableView reloadData];
}

當(dāng)點擊節(jié)點時,判斷有無孩子節(jié)點,進行當(dāng)前數(shù)組的新增或刪除。

插入節(jié)點

這里只添加孩子節(jié)點中一層,不進行遞歸操作。

- (void)insertOulineWithParentOutline:(PDFOutline *)parentOutline
{
    NSInteger baseIndex = [self.arrData indexOfObject:parentOutline];
    
    for (int i = 0; i < parentOutline.numberOfChildren; i++)
    {
        PDFOutline *tempOuline = [parentOutline childAtIndex:i];
        tempOuline.isOpen = NO;
        [self.arrData insertObject:tempOuline atIndex:baseIndex + i + 1];
    }
}

刪除節(jié)點

首先判斷該節(jié)點下有無孩子節(jié)點,若無直接返回;

判斷每個孩子節(jié)點是否還存在孩子節(jié)點,若有,則進行遞歸操作逐一進行刪除。

注意:此處是為了點擊回收父節(jié)點時將該父節(jié)點下的所有子節(jié)點(不論層級)全部刪除。

- (void)removeOutlineWithParentOuline:(PDFOutline *)parentOutline
{
    if (parentOutline.numberOfChildren <= 0)
    {
        return;
    }
    
    for (int i = 0; i < parentOutline.numberOfChildren; i++)
    {
        PDFOutline *node = [parentOutline childAtIndex:i];
        
        if (node.numberOfChildren > 0 && node.isOpen)
        {
            [self removeOutlineWithParentOuline:node];
            
            NSInteger index = [self.arrData indexOfObject:node];
            
            if (index)
            {
                [self.arrData removeObjectAtIndex:index];
            }
        }
        else
        {
            if ([self.arrData containsObject:node])
            {
                NSInteger index = [self.arrData indexOfObject:node];
                
                if (index)
                {
                    [self.arrData removeObjectAtIndex:index];
                }
            }
        }
    }
}

判斷節(jié)點深度,一遍設(shè)置顯示偏移量

- (NSInteger)findDepthWithOutline:(PDFOutline *)outline
{
    NSInteger depth = -1;
    PDFOutline *tempOutline = outline;
    
    while (tempOutline.parent != nil)
    {
        depth++;
        tempOutline = tempOutline.parent;
    }
    
    return depth;
}
image

實現(xiàn) PDF 搜索功能

這里搜索功能主要靠下述方法實現(xiàn)

// Begins a find, searching the document for string.  Search results are handled via a 
// PDFDocumentDidFindMatchNotification or if the delegate implements -[didMatchString:]. Supported options are: 
// NSCaseInsensitiveSearch, NSLiteralSearch, and NSBackwardsSearch.
- (void)beginFindString:(NSString *)string withOptions:(NSStringCompareOptions)options;

調(diào)用此方法之前,首先需將 PDFDocument 設(shè)置代理,通過 PDFDocument 的代理進行回調(diào)。獲取 PDFSelection 對象,

#pragma mark - --- PDFDocument Delegate ---

- (void)didMatchString:(PDFSelection *)instance
{
    [self.arrData addObject:instance];
    [self.tableView reloadData];
}

再根據(jù) selection 對象顯示搜索內(nèi)容。

image

PDF 縮放功能

調(diào)用下述方法即可對 PDFView 進行縮放,

// Zooming changes the scaling by root-2.
- (IBAction)zoomIn:(nullable id)sender;
@property (nonatomic, readonly) BOOL canZoomIn;

- (IBAction)zoomOut:(nullable id)sender;
@property (nonatomic, readonly) BOOL canZoomOut;

實現(xiàn)雙擊縮放或還原:

這里通過設(shè)置 pdfView 的 scaleFactor 屬性即可實現(xiàn),注意scaleFactorForSizeToFit屬性是當(dāng)前 PDF 充滿屏幕的比例。

- (void)doubleTapAction
{   
    if (self.pdfView.scaleFactor == self.pdfView.scaleFactorForSizeToFit)
    {
        [UIView animateWithDuration:0.2 animations:^{
            self.pdfView.scaleFactor = self.pdfView.scaleFactorForSizeToFit * 4;
        }];
    }
    else
    {
        [UIView animateWithDuration:0.2 animations:^{
            self.pdfView.scaleFactor = self.pdfView.scaleFactorForSizeToFit;
        }];
    }
}

Demo

GitHub : https://github.com/japho/PDFDemo

本文作者:Japho

本文原地址:https://japho.top/2018/11/21/guideline-of-pdfkit/

未經(jīng)本人同意請勿擅自轉(zhuǎn)載,轉(zhuǎn)載請注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容