引言:iOS對(duì)瀏覽文件提供了方便的SDK,讓開(kāi)發(fā)者調(diào)用實(shí)現(xiàn)各自的需求,之前利用UIWebView直接加載本地或者網(wǎng)絡(luò)路徑瀏覽文件薄货。最近研究了一下UIDocumentInteractionController和QLPreviewController去預(yù)覽文件,個(gè)人感覺(jué)各自有各自的優(yōu)缺點(diǎn),需要根據(jù)具體的業(yè)務(wù)場(chǎng)景選擇適合的方式蝇狼。
UIDocumentInteractionController的使用方法,以及QuickLook的使用方法倡怎,網(wǎng)上資料已經(jīng)很多了迅耘,這里記錄一下自己學(xué)習(xí)所獲得的知識(shí),和一個(gè)自定義的問(wèn)題监署。
一颤专、是否可以在線預(yù)覽
剛開(kāi)始接觸時(shí)的想法是:是否有在線預(yù)覽功能,UIDocumentInteractionController和QLPreviewController的顯示樣式自帶分頁(yè)效果钠乏,效果看起來(lái)和專(zhuān)業(yè)做文檔預(yù)覽的軟件栖秕,預(yù)覽效果類(lèi)似,那不是太好了晓避!然而現(xiàn)實(shí)很骨感簇捍,查閱了大量資料以及自己測(cè)試之后,我可以確定的答案是:不能在線預(yù)覽俏拱!只能加載本地文件暑塑。
二、UIDocumentInteractionController
使用過(guò)UIDocumentInteractionController的小伙伴都知道彰触,雖然它叫控制器梯投,但是它不是真正意義上的控制器而是繼承自NSObject的。這也就是為什么要遵循代理方法况毅,告訴UIDocumentInteractionController如何去顯示分蓖,比如顯示在當(dāng)前控制器,顯示的Rect等尔许。
下面是實(shí)現(xiàn)代碼:
#import "ViewController.h"
@interface ViewController ()<UIDocumentInteractionControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title=@"預(yù)覽";
NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"iOS開(kāi)發(fā)指南.pdf" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:urlStr];
UIDocumentInteractionController *documentVc = [UIDocumentInteractionController interactionControllerWithURL:url];
documentVc.delegate = self;
[documentVc presentPreviewAnimated:YES];
}
#pragma mark - UIDocumentInteractionController 代理方法
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller{
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller{
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller{
return self.view.bounds;
}
顯示的樣子是這樣的:
如果下面的代理方法不實(shí)現(xiàn)的話
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller{
return self.view;
}
是這樣子的:
在圖2的狀態(tài)單擊也會(huì)出現(xiàn)圖1的效果么鹤,隱藏導(dǎo)航欄。但是有個(gè)問(wèn)題是味廊,無(wú)法自定義這個(gè)導(dǎo)航欄蒸甜,可能說(shuō)無(wú)法自定義這有點(diǎn)絕對(duì),只是我現(xiàn)在還沒(méi)有找到好的辦法余佛,如果有哪位知道的話柠新,煩請(qǐng)指教,謝謝辉巡!
三恨憎、QLPreviewController
QLPreviewController的實(shí)現(xiàn)和UIDocumentInteractionController類(lèi)似,但是QLPreviewController是真正的控制器。兩者之間雖然實(shí)現(xiàn)效果相同憔恳,但是還是存在區(qū)別的瓤荔。
比如:QLPreviewController可以一起瀏覽多個(gè)文件,而UIDocumentInteractionController一次只能瀏覽一個(gè)文件钥组。
使用QLPreviewController之前输硝,需要導(dǎo)入QuickLook.framework,并遵守其數(shù)據(jù)源和代理方法程梦。實(shí)現(xiàn)代碼如下:
#import "ViewController.h"
#import <QuickLook/QuickLook.h>
@interface ViewController ()<QLPreviewControllerDataSource,QLPreviewControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//控制當(dāng)前控制器對(duì)應(yīng)的導(dǎo)航條顯示的內(nèi)容
self.navigationItem.title=@"預(yù)覽";
NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"iOS開(kāi)發(fā)指南.pdf" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:urlStr];
self.fileUrl = url;
if ([QLPreviewController canPreviewItem:(id<QLPreviewItem>)url]) {
QLPreviewController *qlVc = [[QLPreviewController alloc] init];
qlVc.view.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
qlVc.delegate = self;
qlVc.dataSource = self;
qlVc.navigationController.navigationBar.userInteractionEnabled = YES;
qlVc.view.userInteractionEnabled = YES;
[self presentViewController:qlVc animated:YES completion:nil];
}
}
#pragma mark - QLPreviewController 代理方法
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller{
return 1;
}
- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
return self.fileUrl;
}
@end
實(shí)現(xiàn)的效果如圖2是一樣的点把,但是使用QLPreviewController能夠?qū)崿F(xiàn)替換導(dǎo)航欄的問(wèn)題,比如我們的需求為不需要右上角調(diào)出Menu項(xiàng)供選擇作烟,但是需要標(biāo)題和返回按鈕愉粤,在下面的代碼中這樣修改:
if ([QLPreviewController canPreviewItem:(id<QLPreviewItem>)url]) {
QLPreviewController *qlVc = [[QLPreviewController alloc] init];
qlVc.view.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
qlVc.delegate = self;
qlVc.dataSource = self;
qlVc.navigationController.navigationBar.userInteractionEnabled = YES;
qlVc.view.userInteractionEnabled = YES;
[self.view addSubview:qlVc.view];
[self presentViewController:qlVc animated:YES completion:nil];
}
將QLPreviewController的view添加到當(dāng)前控制器的view上,如下:
[self.view addSubview:qlVc.view];
但是這樣的話又出現(xiàn)了新的問(wèn)題拿撩,其本身的導(dǎo)航欄不見(jiàn)了衣厘,顯示在你眼前的是你自己導(dǎo)航欄,如果需求改為需要右上角功能压恒,這時(shí)就尷尬了影暴,所以這其中的取舍需要具體的業(yè)務(wù)來(lái)決定了。
接下來(lái)看下QLPreviewControllerDataSource方法:
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller{
return 1;
}
這里我返回的PreviewItems的數(shù)量為1探赫,就是一次加載一個(gè)文件型宙,這里可以是多個(gè)文件的數(shù)組個(gè)數(shù),也就是某個(gè)本地路徑下的多個(gè)文件伦吠,大家可以自己實(shí)現(xiàn)下妆兑。
- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
return self.fileUrl;
}
返回的當(dāng)前預(yù)覽的文件QLPreviewItem,controller:當(dāng)前預(yù)覽控制器,index:當(dāng)前預(yù)覽的第幾個(gè)文件毛仪。 這里為什么返回Url呢搁嗓,進(jìn)入QLPreviewItem頭文件你就會(huì)明白了:
QL_EXPORT @protocol QLPreviewItem <NSObject>
@required
/*!
* @abstract The URL of the item to preview.
* @discussion The URL must be a file URL.
*/
@property(readonly, nonnull, nonatomic) NSURL * previewItemURL;
@optional
/*!
* @abstract The item's title this will be used as apparent item title.
* @discussion The title replaces the default item display name. This property is optional.
*/
@property(readonly, nullable, nonatomic) NSString * previewItemTitle;
@end
/*!
* @abstract This category makes NSURL instances as suitable items for the Preview Controller.
*/
@interface NSURL (QLPreviewConvenienceAdditions) <QLPreviewItem>
其實(shí)NSURL的分類(lèi)遵循了QLPreviewItem協(xié)議,所以是可以返回Url的箱靴,這里可以返回一個(gè)Url數(shù)組腺逛。這就是預(yù)覽多個(gè)文件時(shí)的數(shù)據(jù)源方法,注意:以上兩個(gè)方法是@required的衡怀,必須需要實(shí)現(xiàn)的棍矛。
QLPreviewController還有一些代理方法,供你選擇性實(shí)現(xiàn)抛杨,比如說(shuō):
- (void)previewControllerWillDismiss:(QLPreviewController *)controller;
QLPreviewController將要消失的時(shí)候你可以處理一些邏輯够委,還有一些就不列舉了,大家可以進(jìn)入頭文件了解一下怖现。
自定義預(yù)覽控制器慨绳,一直沒(méi)有好的辦法,如有知道的童鞋,煩請(qǐng)指教下脐雪,順便說(shuō)下,剛剛接觸這塊恢共,如有錯(cuò)誤战秋,也請(qǐng)指出,多謝讨韭!