Считыватель PDF с CGPDFDocumentRef
Я собираюсь сделать PDF-ридер и пробую два возможных решения:
- UIWebView
- CGPDFDocumentRef
Первый очень прост, но медленнее второго. Для второго я нашел учебник, и я могу просмотреть PDF, и я могу увеличить его с помощью движения двумя пальцами. Но на данный момент я не могу сделать 2 вещи:
1) Просмотр PDF в альбомной ориентации, поддерживая правильные пропорции. 2) Сделайте увеличение / уменьшение масштаба с помощью двойного нажатия на экран.
Эти функции уже реализованы в UIWebView, но, как уже было сказано, он немного медленный и открывает весь документ PDF, а не только одну страницу (поэтому мне нужно разделить файл на множество "одностраничных файлов PDF").
Кто-нибудь может помочь мне с некоторыми ссылками / ссылками / кодом о таких проблемах?
3 ответа
С CGPDFDocumentRef
, вы должны получить каждую страницу с CGPDFDocumentGetPage
а затем получить преобразование рисунка с CGPDFPageGetDrawingTransform
и применить это к CGContextRef
прежде чем нарисовать страницу.
Помещение представления с вашей страницей PDF в UIScrollView позволит вам увеличивать и уменьшать масштаб, если вы включите масштабирование. Вы также можете нарисовать его с коэффициентом масштабирования, используя
CGContextTranslateCTM (context, -sourceRect.origin.x * zoom, -sourceRect.origin.y * zoom);
CGContextScaleCTM (context, zoom, zoom);
Но вы все равно столкнетесь с проблемой, что очень сложные страницы PDF будут медленно отображаться, и каждый раз, когда вы звоните CGContextDrawPDFPage(context, page);
он должен отображать всю страницу, например, при изменении уровня масштабирования. Есть способы обойти это, такие как рисование в CATiledLayer.
Именно в примере, который я нашел, он использует CATiledLayer.
Здесь есть мой код:
- (void)viewDidLoad
{
[super viewDidLoad];
CFURLRef pdfURL = CFBundleCopyResourceURL(
CFBundleGetMainBundle(),
CFSTR(filename),
CFSTR("pdf"), NULL);
myDocumentRef = CGPDFDocumentCreateWithURL(pdfURL);
myPageRef = CGPDFDocumentGetPage(myDocumentRef, 1);
CGRect pageRect = CGRectMake(0, 0, 320, 480);
tiledLayer = [CATiledLayer layer];
tiledLayer.delegate = self;
tiledLayer.tileSize = CGSizeMake(1024.0, 1024.0);
tiledLayer.levelsOfDetail = 1000;
tiledLayer.levelsOfDetailBias = 1000;
tiledLayer.frame = pageRect;
myContentView = [[UIView alloc] initWithFrame:pageRect];
[myContentView.layer addSublayer:tiledLayer];
CGRect viewFrame = self.view.frame;
viewFrame.origin = CGPointZero;
scrollView = [[UIScrollView alloc] initWithFrame:viewFrame];
scrollView.delegate = self;
scrollView.contentSize = pageRect.size;
scrollView.maximumZoomScale = 100;
[scrollView addSubview:myContentView];
[self.view addSubview:scrollView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return myContentView;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx));
CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(myPageRef, kCGPDFCropBox, layer.bounds, 0, true));
CGContextDrawPDFPage(ctx, myPageRef);
}
Эта часть прекрасно работает, но если я хочу представить ландшафтный режим, мне нужно изменить эту часть:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if( (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeRight)){
//SOMETHING TO DO FOR LANDSCAPE MODE
}
else if((interfaceOrientation == UIInterfaceOrientationPortrait)){
//SOMETHING TO DO TO RESTORE TO PORTRAIT
}
// Return YES for supported orientations
return ((interfaceOrientation == UIInterfaceOrientationPortrait) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}
Я старался практически все, но я не могу найти хорошее решение!
Вы можете вызвать метод рисования слоя любого слоя вручную, сказав [yourLayer setNeedsDisplay]