記錄一個心碎的歷程,公司項目要求查看pdf合同文件,(合同)這里劃重點屿良。暫行方案,就是將pdf下載到本地痘昌,然后寫入沙盒緩存,加載pdf本地文件炬转。這是前提和方式辆苔。
當(dāng)然我想,如果只是下載加載pdf扼劈,那網(wǎng)上基本一大片都是解決方案驻啤,code4app上一大堆demo,但是荐吵,重點來了骑冗,合同上是有電子簽章的赊瞬,網(wǎng)上下載的demo基本都顯示不了電子簽章。
電子簽章如下: ?
當(dāng)然還有圓公章的電子版贼涩,還得打碼懶得傳了巧涧。
第一階段,我們采用webview加載pdf遥倦,當(dāng)然也不是直接用UIWebView谤绳,使用WKWebView+js注入,反正網(wǎng)上一搜一大堆谊迄,直接上代碼闷供。(可以顯示電子簽章)
WKWebViewConfiguration*config = [[WKWebViewConfigurationalloc]init];
WKUserContentController* wkUController = [[WKUserContentControlleralloc]init];
config.userContentController= wkUController;
// 注入JS對象名稱AppModel烟央,當(dāng)JS通過AppModel來調(diào)用時统诺,
// 我們可以在WKScriptMessageHandler代理中接收到
[config.userContentControlleraddScriptMessageHandler:selfname:@"AppModel"];
NSString*js =@"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript*wkUserScript = [[WKUserScriptalloc]initWithSource:js
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES];
// 添加自適應(yīng)屏幕寬度js調(diào)用的方法
[wkUControlleraddUserScript:wkUserScript];
WKWebView*webView = [[WKWebViewalloc]initWithFrame:CGRectMake(0,0,kScreenW,kScreenH-64)
configuration:config];
webView.backgroundColor= [UIColorwhiteColor];
webView.UIDelegate=self;
webView.navigationDelegate=self;
[self.viewaddSubview:webView];
_webView= webView;
第二階段,使用webview加載疑俭,雖然手勢放大縮小粮呢,都沒有問題,但是放大后很模糊钞艇,達不到pdf給人的清晰感覺啄寡,文件確實是清晰的。查了很多demo哩照,發(fā)現(xiàn)用coreImage重繪弄的很大神挺物,而且封裝的很方便,代表作品是star很多的?vrf/reader 飘弧。支持分頁识藤,標記選擇等等,很多功能次伶,缺點就是不顯示電子簽章(pass)痴昧,優(yōu)點是可修改性強,代碼修修改改可以做成自己需要的樣子冠王。
第三階段赶撰,查看到了OC自帶的系統(tǒng)加載文件控制器,UIDocumentInteractionController和QLPreviewController柱彻,逐個說吧豪娜,基本使用差不多,但是UIDocumentInteractionController基于NSObject哟楷,QLPreviewController是真正的控制器侵歇,第二個可以繼承,重寫子類吓蘑。
1.UIDocumentInteractionController
UIDocumentInteractionController*documentVc = [UIDocumentInteractionControllerinteractionControllerWithURL:url];
documentVc.delegate=self;
[documentVcpresentPreviewAnimated:YES];
實現(xiàn)代理方法
#pragma mark - UIDocumentInteractionController 代理方法
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller{
returnself;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller{
returnself.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller{
returnself.view.bounds;
}
實現(xiàn)效果很好惕虑,清晰度坟冲,手勢識別,但是上面自帶導(dǎo)航欄溃蔫,而且是系統(tǒng)的很丑的導(dǎo)航健提,首先不能隱藏,隱藏沒法自定義伟叛,總之不好用私痹。
2.QLPreviewController這是個系統(tǒng)控制器,可繼承實現(xiàn)子類
MINPDFViewController*preview = [[MINPDFViewControlleralloc]init];
UINavigationController*nav = [[UINavigationControlleralloc]initWithRootViewController:preview];
preview.url=self.mUrl;
[self.navigationControllerpresentViewController:navanimated:YEScompletion:nil];
注意到包裹了一層nav统刮,如果直接present這個子類紊遵,那恭喜你,和doc控制器一樣侥蒙,里面不可更改導(dǎo)航欄的東西暗膜,具體可以實踐操作一樣,
在繼承控制器實現(xiàn)類里鞭衩。
UILabel*titleView = [[UILabelalloc]initWithFrame:CGRectMake(0,0,36,20)];
titleView.font= [UIFontsystemFontOfSize:18];
titleView.text=@"預(yù)覽";
self.navigationItem.titleView= titleView;
UIButton*backButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
[backButtonsetImage:[UIImageimageNamed:@"btnBack_black"]forState:UIControlStateNormal];
self.navigationItem.leftBarButtonItem= [[UIBarButtonItemalloc]initWithCustomView:backButton];
self.delegate=self;
self.dataSource=self;
不出意外学搜,修改了返回鍵和titleview,(代碼是精簡的)论衍。但是iOS11下瑞佩,在右側(cè)rightBarButtonItem 有個系統(tǒng)分享打開的按鈕。嘗試替換坯台,不行炬丸,設(shè)置為nil不行,最后在stackoverflow一個大神回復(fù)的一句話找到了解決辦法 在viewdidload中定義一個timer
[NSTimerscheduledTimerWithTimeInterval:0.01
target:self
selector:@selector(hideRightButton)
userInfo:nil
repeats:YES];
實現(xiàn)方法:
- (void)hideRightButton{
[[selfnavigationItem]setRightBarButtonItem:nilanimated:NO];
}實測隱藏有效蜒蕾,感覺像是view加載完成前稠炬,系統(tǒng)保護控制器不受修改,完成后才可以隱藏滥搭,但是使用延時方法隱藏?zé)o效酸纲。
一切看上去都那么美好,直到上了真機瑟匆,在iOS11下闽坡,剛進來是好的,下拉愁溜,有一塊空白疾嗅,大約64,看過wwdc的應(yīng)該知道那個任性的sb說過這個問題冕象,如果是tableview scrollerview 可以通過屬性關(guān)閉這個特性
if(@available(iOS11.0, *)) {
_tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}else{
self.automaticallyAdjustsScrollViewInsets=NO;
}
我找了無數(shù)方法代承,還是遍歷不出,系統(tǒng)QLPre控制器的 scrollerview渐扮,知道這個屬性也沒用论悴,一切進入了死角掖棉,還是stackoverflow 用蹩腳英語查了下解決辦法,有人用viewcontroller的view添加 precontroller的view膀估,實驗了下確實可行幔亥,但是百度上查的辦法并不行。試試這個察纯。
QLPreviewController* previewer = [[QLPreviewControlleralloc]init];
previewer.dataSource=self;
previewer.delegate=self;
CGFloatwidth =self.view.frame.size.width;
CGFloatheight =self.view.frame.size.height;
previewer.view.frame=CGRectMake(0,64, width, height-64);
[self.viewaddSubview:previewer.view];
NSString*version = [UIDevicecurrentDevice].systemVersion;
if(version.floatValue>=10.0) {
[selfaddChildViewController:previewer];
}else{
[previewerdidMoveToParentViewController:self];
}
代理實現(xiàn)還是一樣的
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController*)controller {
return1;
}
- (id)previewController:(QLPreviewController*)controller previewItemAtIndex:(NSInteger)index {
returnself.url;
}
這樣還有個好處帕棉,就是導(dǎo)航欄變成了之前push進當(dāng)前控制器的導(dǎo)航欄,沒有系統(tǒng)控件饼记,因為你只加載了view香伴,解決之前自定義問題,同時解決了下掉64的問題具则。
但是即纲,沒錯,但是又來了乡洼,在iOS9下崇裁,還是不顯示簽章匕坯,這是系統(tǒng)問題束昵,查了好多資料,不過根據(jù)向下兼容兩版本的原則葛峻,我們暫行锹雏,10 11使用系統(tǒng)控制器加載pdf,清晰大氣术奖,縮放手勢完整礁遵,9及9以下用戶,還是用webview加載采记,并行的方式佣耐,其他方法還在繼續(xù)尋找中,歡迎指正問題唧龄,提供解決辦法兼砖。github鏈接