IOS--PDF显示(CGPDFDocumentRef)

摘要: 学习使用自定义view加载显示pdf;

前言

在IOS中预览pdf文件,显示pdf文件一般使用两种方式,一种是UIWebView,这种方式怎么说呢优点就是除了简单还是简单,直接显示pdf文件;另外的一种是自定义UIView,配合CGPDFDocumentRef读取pdf文件里面的内容,在自定义的drawRect方法中描绘获取的pdf内容;其实还有一种的方式,就是苹果在IOS4.0后,apple推出新的文件预览控件:QLPreveiewController,支持pdf文件阅读。今天我主要写的是自定义View+CGPDFDocumentRef显示pdf文件;

(一)先运用CGPDFDocumentRef获取指定的pdf内容;下面是我写出的获取内容的方法;

 1 //用于本地pdf文件
 2 - (CGPDFDocumentRef)pdfRefByFilePath:(NSString *)aFilePath {
 3     CFStringRef path;
 4     CFURLRef url;
 5     CGPDFDocumentRef document;
 6
 7     path = CFStringCreateWithCString(NULL, [aFilePath UTF8String], kCFStringEncodingUTF8);
 8     url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, NO);
 9     document = CGPDFDocumentCreateWithURL(url);
10
11     CFRelease(path);
12     CFRelease(url);
13
14     return document;
15 }
16
17 - (NSString *)getPdfPathByFile:(NSString *)fileName {
18     return [[NSBundle mainBundle] pathForResource:fileName ofType:@".pdf"];
19 }
20
21 //用于网络pdf文件
22 - (CGPDFDocumentRef)pdfRefByDataByUrl:(NSString *)aFileUrl {
23     NSData *pdfData = [NSData dataWithContentsOfFile:aFileUrl];
24     CFDataRef dataRef = (__bridge_retained CFDataRef)(pdfData);
25
26     CGDataProviderRef proRef = CGDataProviderCreateWithCFData(dataRef);
27     CGPDFDocumentRef pdfRef = CGPDFDocumentCreateWithProvider(proRef);
28
29     CGDataProviderRelease(proRef);
30     CFRelease(dataRef);
31
32     return pdfRef;
33 }

通过文件路径解析pdf文件,返回文件内容。

(二)第二步就是在自定义的View中绘制pdf内容;

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGPDFPageRef pageRef = CGPDFDocumentGetPage([self createPDFFromExistFile], _pageNumber);//获取指定页的内容如_pageNumber=1,获取的是pdf第一页的内容
    CGRect mediaRect = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox);//pdf内容的rect

    CGContextRetain(context);
    CGContextSaveGState(context);

    [[UIColor whiteColor] set];
    CGContextFillRect(context, rect);//填充背景色,否则为全黑色;

    CGContextTranslateCTM(context, 0, rect.size.height);//设置位移,x,y;

    CGFloat under_bar_height = 64.0f;
    CGContextScaleCTM(context, rect.size.width / mediaRect.size.width, -(rect.size.height + under_bar_height) / mediaRect.size.height);

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGContextSetRenderingIntent(context, kCGRenderingIntentDefault);
    CGContextDrawPDFPage(context, pageRef);//绘制pdf

    CGContextRestoreGState(context);
    CGContextRelease(context);
}

以上就是绘制pdf的内容的代码,代码每行我都写了注释,其实都是很好了解的。

当然上面的只是显示pdf指定页的逻辑,要想显示整个pdf文件的内容,需要配合UIScrollView或者是UIPageViewController去实现,原理也很简单,结合上述的逻辑只要传入一个pageIndex的值,刷新页面内容就可以实现。下面是我写的一个列子,pageviewcontroller实现;

- (void)viewDidLoad {
    [super viewDidLoad];
    self.pdfArr = [NSMutableArray array];
    NSDictionary *options = [NSDictionary  dictionaryWithObject:[NSNumber numberWithInteger:UIPageViewControllerSpineLocationMin] forKey:UIPageViewControllerOptionSpineLocationKey];
    self.pageVC = [[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:options];
    _pageVC.view.frame = self.view.bounds;
    _pageVC.delegate = self;
    _pageVC.dataSource = self;
    [self addChildViewController:_pageVC];

    PDFView *testPdf = [[PDFView alloc]initWithFrame:self.view.frame atPage:1 andFileName:@"Reader"];
    CGPDFDocumentRef pdfRef = [testPdf createPDFFromExistFile];
    size_t count = CGPDFDocumentGetNumberOfPages(pdfRef);//这个位置主要是获取pdf页码数;

    for (int i = 0; i < count; i++) {
        UIViewController *pdfVC = [[UIViewController alloc] init];
        PDFView *pdfView = [[PDFView alloc] initWithFrame:self.view.frame atPage:(i+1) andFileName:@"Reader"];
        [pdfVC.view addSubview:pdfView];

        [_pdfArr addObject:pdfVC];
    }

    [_pageVC setViewControllers:[NSArray arrayWithObject:_pdfArr[0]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
    [self.view addSubview:_pageVC.view];

}
//委托方法;
- (UIViewController *)viewControllerAtIndex:(NSInteger)index
{
    //Create a new view controller and pass suitable data.

    if (([_pdfArr count] == 0 )|| (index > [_pdfArr count]) ) {
        return nil;
    }

    NSLog(@"index = %ld",(long)index);

    return (UIViewController *)_pdfArr[index];
}

- (NSUInteger) indexOfViewController:(UIViewController *)viewController
{
    return [self.pdfArr indexOfObject:viewController];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(UIViewController *)viewController];
    if (index == NSNotFound) {
        return nil;
    }

    index++;

    if (index == [_pdfArr count]){
        return  nil;
    }

    return [self viewControllerAtIndex:index];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(UIViewController *)viewController];
    if ((index == 0 ) || (index == NSNotFound)){
        return nil;
    }

    index--;

    return [self viewControllerAtIndex:index];
}

以上就是简单的实现;

(三)对于第三种方法,使用QLPreveiewController去预览pdf,我就没有具体的通过代码去实现pdf的预览,在网络上应该有资源可查;

QLPreveiewController的用法;已经简单的说了一下怎么去预览pdf内容,也是很简单的,如果想要自定义显示的话,需要自己花时间去研究了。

总结

不管是选用哪一种方式,都可以实现加载pdf文件;webview除了简单粗暴但是只能作为简单的浏览,CGPDFDocumentRef需要开发者自己去实现显示的逻辑,但这样可控性会比较好,显示的效果也是可以自定义,QLPreveiewController的话,我没有自己去实现过,所以大家可以去试试。

时间: 2024-09-27 18:29:16

IOS--PDF显示(CGPDFDocumentRef)的相关文章

new Date()在安卓下正常,在IOS下显示不出来

之前用JS在做一个倒计时,在PC端和安卓下面显示没问题,在IOS下显示不出来. 查找了资料,链接我忘记了. 原因是: 在IOS下,new Date("2000-2-22 00:10"),返回的是undefined,因为IOS不支持这种类型格式. 解决方案: 更换下格式:new Date("2000/2/22") 可以正常显示.

IOS 状态栏 显示与隐藏网络活动状态

IOS中显示和隐藏状态栏的网络活动标志 //在向服务端发送请求状态栏显示网络活动标志: [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; //这里是发送服务端请求的代码 //请求结束状态栏隐藏网络活动标志: [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

vue中解决时间在ios上显示NAN的问题

最近在用vue,遇到倒计时在ios上显示为NAN的问题. 因为做的是倒计时支付,思路是获取服务器时间和下单时间,再转成秒级时间戳做差值. 在网上找到说是ios 不支持例如2018-09-01 10:00:59这种"-"连接符. 网上的解决是: var data = '2018-09-01 12:00:00' var time= Date.parse(new Date(data )) 然后用正则匹配改一下,将-替换为/ var date = '2018-09-01 12:00:00' v

将.stl文件转化为.dae并动态加载到SceneKit显示(ios中显示3d模型)

ios8之后苹果推出了一个3D模型渲染框架.SceneKit.但是国内针对这方面的教程并不是很多.前两天搞了一下也是一头雾水,终于把最基础的内容搞明白了之后,写下这篇随笔作为cnblogs的开篇,希望能一直写下去. SceneKit现在可以支持有限的几种模型,截止到我写这篇文章为止似乎只有.dae和.abc后一种模型我没有使用过.这篇文章只针对.dae模型写. 首先如果是希望加载一个已有的,不需要程序在运行的时候动态添加的dae模型.那么我们可以直接新建一个game类型的工程.在选项中选择Sce

iOS 状态栏显示/隐藏

iOS 10为止,将在plist文件中将 View controller-based status bar appearance 设置为NO,就可以用UIApplication设置状态栏. 注意,要在屏幕旋转结束后设置才生效,旋转过程中设置会无效.播放器全屏,竖屏亲测可用. iPhone默认全屏不显示状态栏,iPad默认全屏时显示状态栏 参考 http://www.jianshu.com/p/4196d7cf95f4 http://www.jianshu.com/p/ce4e70d441f9 h

IOS - PDF合并

#pragma mark - Merge PDF - (void)mergePDF { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *filePath1 = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"阅办卡.pdf"]; NSString *fi

ios日期显示NaN

ios中js通过getMonth()获取到的日期显示NaN,而在其他地方如pc.安卓都是ok的,这是为什么呢,原来这里有个ios的兼容问题,需要将日期中的"-"替换为"/" var time = new Date("2017-6-21 18:00:00".replace(/-/g,'/')); alert(time.getMonth())//都可以正常显示"6"了

上手iOS常见问题——iOS模拟器显示错位问题解决

由于刚刚开始学习iOS开发,所以其中肯定会碰到很多问题,也可能是大家也遇到的问题.我也会在自己的学习过程中碰到的问题和解决方案写出来,与大家一起分享.本篇博客要解决的问题是iOS模拟器的显示与Main.storyboard中布局不一致或者说错误的问题. (1)新建一个iOS Application项目,右侧选择Single View Application.点击Next,项目名称任意,下面的Devices选择iPhone,然后创建成功. (2)然后在Main.storyboard中进行界面设计,

iOS 8显示应用角标

1. iOS 8角标显示须要用户授权,可在应用启动时请求授权: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { UIUserNotificationType types = UIUserNot

iOS UIPickerView 显示全国省市

效果图 #import "ViewController.h" @interface ViewController () @property(strong,nonatomic)UIPickerView *myPickView1; @property(strong,nonatomic)NSArray *guo; @property(strong,nonatomic)NSMutableArray *sheng; @property(strong,nonatomic)NSMutableArra