iOS从UIViews创建PDF

时间:2012-10-12 00:40:44

标签: ios cocoa-touch pdf-generation calayer

我目前正在使用CALayerrenderInContext方法从iOS中的UIView创建PDF文档。

我面临的问题是标签的清晰度。我创建了一个UILabel子类,它会覆盖drawLayer,如下所示:

/** Overriding this CALayer delegate method is the magic that allows us to draw a vector version of the label into the layer instead of the default unscalable ugly bitmap */
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
    if (!layer.shouldRasterize && isPDF)
        [self drawRect:self.bounds]; // draw unrasterized
    else
        [super drawLayer:layer inContext:ctx];
}

这种方法让我可以画出漂亮的文字,然而,问题在于我无法控制的其他视图。是否有任何方法可以让我对UITableViewUIButton中嵌入的标签执行类似的操作。我想我正在寻找一种方法来迭代视图堆栈并做一些事情让我画出更清晰的文本。

这是一个例子: 这个文本很好地呈现(我的自定义UILabel子类) Imgur

标准分段控件中的文字不那么尖锐:

Imgur

编辑:我正在将上下文绘制到我的PDF中,如下所示:

UIGraphicsBeginPDFContextToData(self.pdfData, CGRectZero, nil);
pdfContext = UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil);
[view.layer renderInContext:pdfContext];

1 个答案:

答案 0 :(得分:2)

我最终遍历视图层次结构并将每个UILabel设置为覆盖drawLayer的自定义子类。

以下是我浏览视图的方式:

+(void) dumpView:(UIView*) aView indent:(NSString*) indent {
    if (aView) {
        NSLog(@"%@%@", indent, aView);      // dump this view

        if ([aView isKindOfClass:[UILabel class]])
            [AFGPDFDocument setClassForLabel:aView];

        if (aView.subviews.count > 0) {
            NSString* subIndent = [[NSString alloc] initWithFormat:@"%@%@",
                               indent, ([indent length]/2)%2==0 ? @"| " : @": "];
            for (UIView* aSubview in aView.subviews)
                [AFGPDFDocument dumpView:aSubview indent:subIndent];
        }
    }
}

我如何改变课程:

+(void) setClassForLabel: (UIView*) label {
    static Class myFancyObjectClass;
    myFancyObjectClass = objc_getClass("UIPDFLabel");
    object_setClass(label, myFancyObjectClass);
}

比较:

旧:

Image

新:

Imgur

不确定是否有更好的方法可以做到这一点,但它似乎适用于我的目的。

编辑:找到一种更通用的方法,不涉及更改类或遍历整个视图层次结构。我正在使用方法调配。如果你愿意,这种方法还可以让你做一些很酷的事情,比如用边框包围每个视图。首先,我使用UIView+PDF方法的自定义实现创建了一个类别drawLayer,然后在load方法中使用了以下内容:

// The "+ load" method is called once, very early in the application life-cycle.
// It's called even before the "main" function is called. Beware: there's no
// autorelease pool at this point, so avoid Objective-C calls.
Method original, swizzle;

// Get the "- (void) drawLayer:inContext:" method.
original = class_getInstanceMethod(self, @selector(drawLayer:inContext:));
// Get the "- (void)swizzled_drawLayer:inContext:" method.
swizzle = class_getInstanceMethod(self, @selector(swizzled_drawLayer:inContext:));
// Swap their implementations.
method_exchangeImplementations(original, swizzle);

从这里的示例开始:http://darkdust.net/writings/objective-c/method-swizzling