Не секрет, что PDF документ в приложении можно показать в UIWebView. Но, что делать, если вас не устраивает то, как UIWebView отображает документ? Может быть вы хотите сделать свой механизм перехода по страницам?
В iOS PDF можно отобразить через CoreGraphics. При использовании этого подхода каждая страница рисуется отдельно. Т.е. если нужно сделать переход по страницам в документе — нужно будет все делать вручную.
Итак, предположим, что у нас в Bundle приложения лежит PDF-файл idevby.pdf. Как его отобразить? Создадим класс PDFView, который будет это отображать:
@interface PDFView : UIView @end
В классе перекроем метод drawRect::
- (void)drawRect:(CGRect)rect { // путь до документа CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"idevby" ofType:@"pdf"]];// открываем документ CGPDFDocumentRef pdfDocument = CGPDFDocumentCreateWithURL(url);
// если в документе нет страниц - ничего отображать не нужно if ( CGPDFDocumentGetNumberOfPages(pdfDocument) > 0 ) { // получим первую страницу (страницы нумеруются с первой) CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument, 1);
// получим необходимое преобразование CGAffineTransform t = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFCropBox, self.bounds, 0, 1);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
// применим преобразование CGContextTranslateCTM(context, 0, self.bounds.size.height); CGContextScaleCTM(context, 1, -1); CGContextConcatCTM(context, t);
// отрисуем страницу CGContextDrawPDFPage(context, pdfPage);
CGContextRestoreGState(context); }
// закроем документ CGPDFDocumentRelease(pdfDocument); }
Рассмотрим основные моменты.
При отрисовке PDF-страницы мы сохраняем состояние контекста, а затем восстанавливаем его:
CGContextSaveGState(context); ... CGContextRestoreGState(context);
Этого можно было бы и не делать, но если вы захотите рисовать что-то после отрисовки PDF-страницы — это необходимо, иначе то, что вы нарисуете может быть искривлено.
Нам необходимо отразить контекст по вертикали, иначе документ будет показан «вверх ногами». Это связано с тем, что в данном случае ось Y направлена снизу вверх.
CGContextTranslateCTM(context, 0, self.bounds.size.height); CGContextScaleCTM(context, 1, -1);
Ну и самое интересное:
CGAffineTransform t = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFCropBox, self.bounds, 0, 1); ... CGContextConcatCTM(context, t);CGContextDrawPDFPage(context, pdfPage);
Функция CGPDFPageGetDrawingTransform возвращает трансформацию для контекста, которую нужно применить, чтобы целиком отобразить заданную область страницы в заданной области view. Трансформацию применяет функция CGContextConcatCTM. Первым аргументом функции CGPDFPageGetDrawingTransform является страница, которую хотим отобразить. Второй аргумент — область документа для отображения. Области определены так:
enum CGPDFBox { kCGPDFMediaBox = 0, kCGPDFCropBox = 1, kCGPDFBleedBox = 2, kCGPDFTrimBox = 3, kCGPDFArtBox = 4 };
Третий аргумент — область на view, где будет отображена страница, в данном случае мы используем всю область. Четвертый аргумент — угол вращения в градусах, должен быть обязательно кратным 90. Пятый аргумент — сохранять ли пропорции сторон при отрисовке.
Конечно-же, этот способ более трудоемкий, чем способ с использованием UIWebView. Но, используя такой подход, мы можем получить больше возможностей для кастомизации отображения PDF. Есть и минус данного подхода — если в документе есть ссылки — они не будут активными и необходимо будет применять дополнительные средства.
На этом все, спасибо за внимание. Загрузить исходный код можно отсюда.
Напоследок несколько примеров:
CGPDFPageGetDrawingTransform(pdfPage, kCGPDFCropBox, self.bounds, 0, 1)
CGPDFPageGetDrawingTransform(pdfPage, kCGPDFCropBox, self.bounds, 90, 1)
CGPDFPageGetDrawingTransform(pdfPage, kCGPDFCropBox, self.bounds, 90, 0)
CGPDFPageGetDrawingTransform(pdfPage, kCGPDFCropBox, CGRectInset(self.bounds, 50, 100), 0, 1)
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: