我开发了一个应用程序,它使用CATiled Layer在ipad上显示PDF。到目前为止,这么好&但是有一个问题确实让我削减了我的最后一根头发。我有一个嵌入了注释的PDF。每个注释都有一个URL。我可以找到触摸区域的坐标,但问题是如果我的手指下有注释以及如何提取URL以在浏览器中打开它,我怎么能找到?
如果有人可以分享有关如何做到这一点的任何想法,我将非常感谢您的帮助!
提前致谢
答案 0 :(得分:6)
使用CGPDF获取注释并不是很困难,尽管一开始我需要稍微摆弄一下。
//Get the current page ref
CGPDFPageRef currentPdfPage = CGPDFDocumentGetPage(pdfDocumentRef, page);
//Get the page dictionary
CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(currentPdfPage);
CGPDFArrayRef annotsArray;
//Get the Annots array
if(!CGPDFDictionaryGetArray(pageDictionary, "Annots", &annotsArray)) {
//DLog(@"No Annots found for page %d", page);
[self updateProgress];
return;
}
int annotsArrayCount = CGPDFArrayGetCount(annotsArray);
//DLog(@"%d annots found for page %d in file %@", annotsArrayCount, page, _fileName);
NSMutableArray* touchRectsArray = [[NSMutableArray alloc] initWithCapacity:annotsArrayCount];
for (int j=annotsArrayCount; j >= 0; j--) {
int destPageNumber = 0;
NSString* uri = nil;
//DLog(@"%d/%d", j+1, annotsArrayCount);
CGPDFObjectRef aDictObj;
if(!CGPDFArrayGetObject(annotsArray, j, &aDictObj)) {
//DLog(@"%@", @"can't get dictionary object");
continue;
}
CGPDFDictionaryRef annotDict;
if(!CGPDFObjectGetValue(aDictObj, kCGPDFObjectTypeDictionary, &annotDict)) {
//DLog(@"%@", @"can't get annotDict");
continue;
}
//------------
CGPDFDictionaryRef aDict;
CGPDFArrayRef destArray;
if(CGPDFDictionaryGetDictionary(annotDict, "A", &aDict)) {
CGPDFStringRef uriStringRef;
if(CGPDFDictionaryGetString(aDict, "URI", &uriStringRef)) {
char* uriString = (char *)CGPDFStringGetBytePtr(uriStringRef);
uri = [NSString stringWithCString:uriString encoding:NSUTF8StringEncoding];
}
} else {
continue;
}
这会为您提供网址。 得到意见:
CGPDFArrayRef rectArray;
if(!CGPDFDictionaryGetArray(annotDict, "Rect", &rectArray)) {
DLog(@"%@", @"can't get Rect");
}
int arrayCount = CGPDFArrayGetCount(rectArray);
CGPDFReal coords[4];
for (int k = 0; k < arrayCount; k++) {
CGPDFObjectRef rectObj;
if(!CGPDFArrayGetObject(rectArray, k, &rectObj)) {
DLog(@"%@", @"can't get rect data");
}
CGPDFReal coord;
if(!CGPDFObjectGetValue(rectObj, kCGPDFObjectTypeReal, &coord)) {
DLog(@"%@", @"can't get coords");
}
coords[k] = coord;
}
CGRect drawRect = [[SharedConfig valueForKey:@"screenSize"] CGRectValue];
BOOL drawBoxIsLandscape = NO;
if (1 < drawRect.size.width/drawRect.size.height) {
drawBoxIsLandscape = YES;
}
CGRect pageRect = CGRectIntegral(CGPDFPageGetBoxRect(currentPdfPage, kCGPDFMediaBox));
landscape = NO;
if (1 < pageRect.size.width/pageRect.size.height) {
landscape = YES;
}
float ratio = 0.0;
//Get the rect of the clickable area
//CGRect coordsRect = CGRectMake(coords[0], coords[1], coords[2], coords[3]);
//Transform to new coordinate system
CGRect originalRect = CGRectMake(coords[0], (pageRect.size.height-(coords[3]-coords[1]))-coords[1], coords[2]-coords[0], coords[3]-coords[1]);
CGPDFInteger pageRotate = 0;
CGPDFDictionaryGetInteger(pageDictionary, "Rotate", &pageRotate);
if (pageRotate == 90 || pageRotate == 270) {
CGFloat temp = pageRect.size.width;
pageRect.size.width = pageRect.size.height;
pageRect.size.height = temp;
ratio = drawRect.size.height / pageRect.size.height;
}
if (drawBoxIsLandscape) {
ratio = landscape ? (drawRect.size.height/pageRect.size.height) : (drawRect.size.height/pageRect.size.width);
if (landscape && drawRect.size.width < pageRect.size.width*ratio) {
ratio = drawRect.size.width/pageRect.size.width;
} else if (!landscape && drawRect.size.height < pageRect.size.width*ratio) {
ratio = drawRect.size.height/pageRect.size.width;
}
} else {
ratio = landscape ? (drawRect.size.height/pageRect.size.width) : (drawRect.size.height/pageRect.size.height);
if (landscape && drawRect.size.width < pageRect.size.height*ratio) {
ratio = drawRect.size.width/pageRect.size.height;
} else if (!landscape && drawRect.size.height < pageRect.size.height*ratio) {
ratio = drawRect.size.height/pageRect.size.height;
}
}
CGRect calculatedRect = CGRectMake(originalRect.origin.x*ratio, originalRect.origin.y*ratio, originalRect.size.width*ratio, originalRect.size.height*ratio);
if ((landscape && !drawBoxIsLandscape) || (!landscape && drawBoxIsLandscape)) {
CGFloat width = calculatedRect.size.width;
calculatedRect.size.width = calculatedRect.size.height;
calculatedRect.size.height = width;
CGFloat yModifier = drawRect.size.height-(pageRect.size.width*ratio);
CGFloat x = calculatedRect.origin.x;
calculatedRect.origin.x = calculatedRect.origin.y;
calculatedRect.origin.y = drawRect.size.height-(x+calculatedRect.size.height)-yModifier;
}
if (nil != uri) {
[touchRectsArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithCGRect:calculatedRect], @"rect", uri, @"targetUrl", nil]];
}
正如您所看到的,这段代码首先获取注释的矩形,将其转换为设备坐标系,然后根据页面到屏幕的比例,旋转因子等进行一些重新计算,调整大小和重新定位。最后,您将拥有该页面的一系列触摸活动区域。为了处理触摸,可以使用以下简单的解决方案:
- (void) tapGesture:(UIGestureRecognizer*)sender
{
if (UIGestureRecognizerStateEnded == sender.state) {
CGPoint touchPoint = [sender locationInView:self.view];
if (nil != self.touchRects) for (int i=0; i<[self.touchRects count]; i++) {
if (CGRectContainsPoint([[[self.touchRects objectAtIndex:i] objectForKey:@"rect"] CGRectValue], touchPoint)) {
if ([[self.touchRects objectAtIndex:i] objectForKey:@"targetUrl"]) {
NSString* targetUrl = [[self.touchRects objectAtIndex:i] objectForKey:@"targetUrl"];
DLog(@"Hit found for target url: %@", targetUrl);
NSURL* url = [NSURL URLWithString:targetUrl];
[[UIApplication sharedApplication] openURL:url];
} return;
}
}
DLog(@"No hit found for touch at %@", NSStringFromCGPoint(touchPoint));
}
}