iOS 杂谈iOS技术交流收藏ios基础

使用UIDocumentInteractionControlle

2016-09-07  本文已影响7204人  ibabyblue

引言:iOS对浏览文件提供了方便的SDK,让开发者调用实现各自的需求,之前利用UIWebView直接加载本地或者网络路径浏览文件。最近研究了一下UIDocumentInteractionController和QLPreviewController去预览文件,个人感觉各自有各自的优缺点,需要根据具体的业务场景选择适合的方式。


UIDocumentInteractionController的使用方法,以及QuickLook的使用方法,网上资料已经很多了,这里记录一下自己学习所获得的知识,和一个自定义的问题。
一、是否可以在线预览
刚开始接触时的想法是:是否有在线预览功能,UIDocumentInteractionController和QLPreviewController的显示样式自带分页效果,效果看起来和专业做文档预览的软件,预览效果类似,那不是太好了!然而现实很骨感,查阅了大量资料以及自己测试之后,我可以确定的答案是:不能在线预览!只能加载本地文件。
二、UIDocumentInteractionController
使用过UIDocumentInteractionController的小伙伴都知道,虽然它叫控制器,但是它不是真正意义上的控制器而是继承自NSObject的。这也就是为什么要遵循代理方法,告诉UIDocumentInteractionController如何去显示,比如显示在当前控制器,显示的Rect等。
下面是实现代码:

#import "ViewController.h"

@interface ViewController ()<UIDocumentInteractionControllerDelegate>
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.title=@"预览";
    
    NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"iOS开发指南.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;
}

显示的样子是这样的:

UIDocumentInteractionController-1.png

如果下面的代理方法不实现的话

- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller{
    return self.view;
}

是这样子的:

UIDocumentInteractionController-2.png
在图2的状态单击也会出现图1的效果,隐藏导航栏。但是有个问题是,无法自定义这个导航栏,可能说无法自定义这有点绝对,只是我现在还没有找到好的办法,如果有哪位知道的话,烦请指教,谢谢!
三、QLPreviewController
QLPreviewController的实现和UIDocumentInteractionController类似,但是QLPreviewController是真正的控制器。两者之间虽然实现效果相同,但是还是存在区别的。
比如:QLPreviewController可以一起浏览多个文件,而UIDocumentInteractionController一次只能浏览一个文件。
使用QLPreviewController之前,需要导入QuickLook.framework,并遵守其数据源和代理方法。实现代码如下:
#import "ViewController.h"
#import <QuickLook/QuickLook.h>

@interface ViewController ()<QLPreviewControllerDataSource,QLPreviewControllerDelegate>

@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //控制当前控制器对应的导航条显示的内容
    self.navigationItem.title=@"预览";
    
    NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"iOS开发指南.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

实现的效果如图2是一样的,但是使用QLPreviewController能够实现替换导航栏的问题,比如我们的需求为不需要右上角调出Menu项供选择,但是需要标题和返回按钮,在下面的代码中这样修改:

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添加到当前控制器的view上,如下:

[self.view addSubview:qlVc.view];
QLPreviewController-3.png

但是这样的话又出现了新的问题,其本身的导航栏不见了,显示在你眼前的是你自己导航栏,如果需求改为需要右上角功能,这时就尴尬了,所以这其中的取舍需要具体的业务来决定了。
接下来看下QLPreviewControllerDataSource方法:

- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller{
    return 1;
}

这里我返回的PreviewItems的数量为1,就是一次加载一个文件,这里可以是多个文件的数组个数,也就是某个本地路径下的多个文件,大家可以自己实现下。

- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
    return self.fileUrl;
}

返回的当前预览的文件QLPreviewItem,controller:当前预览控制器,index:当前预览的第几个文件。 这里为什么返回Url呢,进入QLPreviewItem头文件你就会明白了:

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>

其实NSURL的分类遵循了QLPreviewItem协议,所以是可以返回Url的,这里可以返回一个Url数组。这就是预览多个文件时的数据源方法,注意:以上两个方法是@required的,必须需要实现的。
QLPreviewController还有一些代理方法,供你选择性实现,比如说:

- (void)previewControllerWillDismiss:(QLPreviewController *)controller;

QLPreviewController将要消失的时候你可以处理一些逻辑,还有一些就不列举了,大家可以进入头文件了解一下。
自定义预览控制器,一直没有好的办法,如有知道的童鞋,烦请指教下,顺便说下,刚刚接触这块,如有错误,也请指出,多谢!

上一篇下一篇

猜你喜欢

热点阅读