iOS PDFKit 開發(fā)指北

前言

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

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

image

核心功能

主要核心功能如下:

PDFView

  • 用于顯示 PDF 阻逮,包括選擇的內(nèi)容,導航秩彤,縮放等功能叔扼。

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 是一個層級關系的對象什燕,他表示 PDF 的大綱(也就是我們常用的書簽)粘勒。每個 PDFOutline 對象都可通過 childAtIndex: 方法獲取出他的孩子對象,注意屎即,這里需要先判斷 numberOfChildren庙睡,以確定該 outline 對象存在多少個孩子節(jié)點,避免下標超界引發(fā)的崩潰剑勾。

實現(xiàn)大綱功能

從 PDFDocument 中獲取 PDFOutline

PDFOutline *outline = self.document.outlineRoot;

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

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

當點擊節(jié)點時埃撵,判斷有無孩子節(jié)點,進行當前數(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é)點深度仪缸,一遍設置顯示偏移量

- (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 設置代理,通過 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)雙擊縮放或還原:

這里通過設置 pdfView 的 scaleFactor 屬性即可實現(xiàn)跨晴,注意scaleFactorForSizeToFit屬性是當前 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)載請注明出處端盆。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怀骤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子焕妙,更是在濱河造成了極大的恐慌蒋伦,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件访敌,死亡現(xiàn)場離奇詭異凉敲,居然都是意外死亡,警方通過查閱死者的電腦和手機寺旺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門爷抓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阻塑,你說我怎么就攤上這事蓝撇。” “怎么了陈莽?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵渤昌,是天一觀的道長。 經(jīng)常有香客問我走搁,道長独柑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任私植,我火速辦了婚禮忌栅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘曲稼。我一直安慰自己索绪,他們只是感情好,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布贫悄。 她就那樣靜靜地躺著瑞驱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窄坦。 梳的紋絲不亂的頭發(fā)上唤反,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音鸭津,去河邊找鬼彤侍。 笑死,一個胖子當著我的面吹牛曙博,可吹牛的內(nèi)容都是我干的拥刻。 我是一名探鬼主播怜瞒,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼父泳,長吁一口氣:“原來是場噩夢啊……” “哼般哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起惠窄,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤蒸眠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后杆融,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楞卡,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年脾歇,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒋腮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡藕各,死狀恐怖池摧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情激况,我是刑警寧澤作彤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站乌逐,受9級特大地震影響竭讳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜浙踢,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一绢慢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧成黄,春花似錦呐芥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闻伶,卻和暖如春滨攻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蓝翰。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工光绕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畜份。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓诞帐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親爆雹。 傳聞我的和親對象是個殘疾皇子停蕉,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容