iOS 从 UIView 创建 PDF

标签 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];
}

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

这是一个例子: 该文本渲染得很好(我的自定义 UILabel 子类) Imgur

标准分段控件中的文本不那么清晰:

Imgur

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

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

最佳答案

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

这是我遍历 View 的方法:

+(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];
        }
    }
}

以及我如何更改类(class):

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

比较:

旧:

Image

新:

Imgur

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

编辑:找到了一种更通用的方法来执行此操作,该方法不涉及更改类或遍历整个 View 层次结构。我正在使用方法调配。如果需要,此方法还可以让您做一些很酷的事情,例如用边框包围每个 View 。首先,我使用 drawLayer 方法的自定义实现创建了一个类别 UIView+PDF,然后在 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

关于iOS 从 UIView 创建 PDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12850684/

相关文章:

Objective-c 复制对象错误

pdf - (手动创建)PDF 在 Ubuntu 上运行良好,但在 Windows 中无法运行?

windows - 为什么 Flash 无法在 Windows 服务中呈现?

ios - 概念化商店结账 channel 的 parse.com 数据结构

iphone - 如何以编程方式绘制三角形

ios - 如何在 iOS 中打开系统字体的高易读性替代品?

iphone - 当点击 backBarButtonItem 时,有没有办法阻止 UIViewController 从 UINavigationController 的堆栈中弹出?

iphone - 从 NSKeyedArchiver 加载单例状态

PDF 命令 - q - Q 是否保存路径?

ios - 在 iOS 中将录制的音频文件转换为 .wav 格式